1
from django.db import backend, transaction
1
from django.db import connection, transaction
2
2
from django.db.models import signals, get_model
3
from django.db.models.fields import AutoField, Field, IntegerField, get_ul_class
3
from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist
4
4
from django.db.models.related import RelatedObject
5
from django.utils.text import capfirst
6
from django.utils.translation import gettext_lazy, string_concat, ngettext
5
from django.db.models.query import QuerySet
6
from django.db.models.query_utils import QueryWrapper
7
from django.utils.encoding import smart_unicode
8
from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _
7
9
from django.utils.functional import curry
8
from django.core import validators
9
from django import oldforms
10
from django import newforms as forms
11
from django.dispatch import dispatcher
14
if not hasattr(__builtins__, 'set'):
15
from sets import Set as set
17
# Values for Relation.edit_inline.
18
TABULAR, STACKED = 1, 2
10
from django.core import exceptions
11
from django import forms
16
from sets import Set as set # Python 2.3 fallback
20
18
RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
22
20
pending_lookups = {}
24
def add_lookup(rel_cls, field):
26
module = rel_cls.__module__
28
# Has the model already been loaded?
29
# If so, resolve the string reference right away
30
model = get_model(rel_cls._meta.app_label, field.rel.to, False)
22
def add_lazy_relation(cls, field, relation, operation):
24
Adds a lookup on ``cls`` when a related field is defined using a string,
28
fk = ForeignKey("AnotherModel")
32
* RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive
35
* The name of a model (i.e "AnotherModel") to indicate another model in
38
* An app-label and model name (i.e. "someapp.AnotherModel") to indicate
39
another model in a different app.
41
If the other model hasn't yet been loaded -- almost a given if you're using
42
lazy relationships -- then the relation won't be set up until the
43
class_prepared signal fires at the end of model initialization.
45
operation is the work that must be performed once the relation can be resolved.
47
# Check for recursive relations
48
if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
49
app_label = cls._meta.app_label
50
model_name = cls.__name__
53
# Look for an "app.Model" relation
55
app_label, model_name = relation.split(".")
57
# If we can't split, assume a model in current app
58
app_label = cls._meta.app_label
61
# Try to look up the related model, and if it's already loaded resolve the
62
# string right away. If get_model returns None, it means that the related
63
# model isn't loaded yet, so we need to pend the relation until the class
65
model = get_model(app_label, model_name, False)
33
field.do_related_class(model, rel_cls)
67
operation(field, model, cls)
35
# Mark the related field for later lookup
36
pending_lookups.setdefault(key, []).append((rel_cls, field))
38
def do_pending_lookups(sender):
40
key = (other_cls.__module__, other_cls.__name__)
41
for rel_cls, field in pending_lookups.setdefault(key, []):
42
field.rel.to = other_cls
43
field.do_related_class(other_cls, rel_cls)
45
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
47
def manipulator_valid_rel_key(f, self, field_data, all_data):
48
"Validates that the value is a valid foreign key"
51
klass._default_manager.get(**{f.rel.field_name: field_data})
52
except klass.DoesNotExist:
53
raise validators.ValidationError, _("Please enter a valid %s.") % f.verbose_name
69
key = (app_label, model_name)
70
value = (cls, field, operation)
71
pending_lookups.setdefault(key, []).append(value)
73
def do_pending_lookups(sender, **kwargs):
75
Handle any pending relations to the sending model. Sent from class_prepared.
77
key = (sender._meta.app_label, sender.__name__)
78
for cls, field, operation in pending_lookups.pop(key, []):
79
operation(field, sender, cls)
81
signals.class_prepared.connect(do_pending_lookups)
56
84
class RelatedField(object):
120
170
# SingleRelatedObjectDescriptor instance.
121
171
def __init__(self, related):
122
172
self.related = related
173
self.cache_name = '_%s_cache' % related.get_accessor_name()
124
175
def __get__(self, instance, instance_type=None):
125
176
if instance is None:
126
177
raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
128
params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
129
rel_obj = self.related.model._default_manager.get(**params)
180
return getattr(instance, self.cache_name)
181
except AttributeError:
182
params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
183
rel_obj = self.related.model._default_manager.get(**params)
184
setattr(instance, self.cache_name, rel_obj)
132
187
def __set__(self, instance, value):
133
188
if instance is None:
134
189
raise AttributeError, "%s must be accessed via instance" % self.related.opts.object_name
191
# The similarity of the code below to the code in
192
# ReverseSingleRelatedObjectDescriptor is annoying, but there's a bunch
193
# of small differences that would make a common base class convoluted.
195
# If null=True, we can assign null here, but otherwise the value needs
196
# to be an instance of the related class.
197
if value is None and self.related.field.null == False:
198
raise ValueError('Cannot assign None: "%s.%s" does not allow null values.' %
199
(instance._meta.object_name, self.related.get_accessor_name()))
200
elif value is not None and not isinstance(value, self.related.model):
201
raise ValueError('Cannot assign "%r": "%s.%s" must be a "%s" instance.' %
202
(value, instance._meta.object_name,
203
self.related.get_accessor_name(), self.related.opts.object_name))
135
205
# Set the value of the related field
136
206
setattr(value, self.related.field.rel.get_related_field().attname, instance)
138
# Clear the cache, if it exists
140
delattr(value, self.related.field.get_cache_name())
141
except AttributeError:
208
# Since we already know what the related object is, seed the related
209
# object caches now, too. This avoids another db hit if you get the
210
# object you just set.
211
setattr(instance, self.cache_name, value)
212
setattr(value, self.related.field.get_cache_name(), instance)
144
214
class ReverseSingleRelatedObjectDescriptor(object):
145
215
# This class provides the functionality that makes the related-object
459
569
if instance is None:
460
570
raise AttributeError, "Manager must be accessed via instance"
572
through = getattr(self.field.rel, 'through', None)
573
if through is not None:
574
raise AttributeError, "Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s's Manager instead." % through
462
576
manager = self.__get__(instance)
464
578
manager.add(*value)
580
class ManyToOneRel(object):
581
def __init__(self, to, field_name, related_name=None,
582
limit_choices_to=None, lookup_overrides=None, parent_link=False):
585
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
586
assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT
587
self.to, self.field_name = to, field_name
588
self.related_name = related_name
589
if limit_choices_to is None:
590
limit_choices_to = {}
591
self.limit_choices_to = limit_choices_to
592
self.lookup_overrides = lookup_overrides or {}
594
self.parent_link = parent_link
596
def get_related_field(self):
598
Returns the Field in the 'to' object to which this relationship is
601
data = self.to._meta.get_field_by_name(self.field_name)
603
raise FieldDoesNotExist("No related field named '%s'" %
607
class OneToOneRel(ManyToOneRel):
608
def __init__(self, to, field_name, related_name=None,
609
limit_choices_to=None, lookup_overrides=None, parent_link=False):
610
super(OneToOneRel, self).__init__(to, field_name,
611
related_name=related_name, limit_choices_to=limit_choices_to,
612
lookup_overrides=lookup_overrides, parent_link=parent_link)
613
self.multiple = False
615
class ManyToManyRel(object):
616
def __init__(self, to, related_name=None, limit_choices_to=None,
617
symmetrical=True, through=None):
619
self.related_name = related_name
620
if limit_choices_to is None:
621
limit_choices_to = {}
622
self.limit_choices_to = limit_choices_to
623
self.symmetrical = symmetrical
625
self.through = through
466
627
class ForeignKey(RelatedField, Field):
467
628
empty_strings_allowed = False
468
def __init__(self, to, to_field=None, **kwargs):
629
def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs):
470
631
to_name = to._meta.object_name.lower()
471
632
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
472
assert isinstance(to, basestring), "ForeignKey(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %r" % (to, RECURSIVE_RELATIONSHIP_CONSTANT)
633
assert isinstance(to, basestring), "%s(%r) is invalid. First parameter to ForeignKey must be either a model, a model name, or the string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
635
assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name)
474
636
to_field = to_field or to._meta.pk.name
475
kwargs['verbose_name'] = kwargs.get('verbose_name', '')
477
if kwargs.has_key('edit_inline_type'):
479
warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
480
kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
482
kwargs['rel'] = ManyToOneRel(to, to_field,
483
num_in_admin=kwargs.pop('num_in_admin', 3),
484
min_num_in_admin=kwargs.pop('min_num_in_admin', None),
485
max_num_in_admin=kwargs.pop('max_num_in_admin', None),
486
num_extra_on_change=kwargs.pop('num_extra_on_change', 1),
487
edit_inline=kwargs.pop('edit_inline', False),
637
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
639
kwargs['rel'] = rel_class(to, to_field,
488
640
related_name=kwargs.pop('related_name', None),
489
641
limit_choices_to=kwargs.pop('limit_choices_to', None),
490
642
lookup_overrides=kwargs.pop('lookup_overrides', None),
491
raw_id_admin=kwargs.pop('raw_id_admin', False))
643
parent_link=kwargs.pop('parent_link', False))
492
644
Field.__init__(self, **kwargs)
494
646
self.db_index = True
530
665
return self.rel.get_related_field().get_db_prep_save(value)
532
def flatten_data(self, follow, obj=None):
667
def value_to_string(self, obj):
534
669
# In required many-to-one fields with only one available choice,
535
670
# select that one available choice. Note: For SelectFields
536
# (radio_admin=False), we have to check that the length of choices
537
# is *2*, not 1, because SelectFields always have an initial
538
# "blank" value. Otherwise (radio_admin=True), we check that the
540
if not self.blank and (not self.rel.raw_id_admin or self.choices):
671
# we have to check that the length of choices is *2*, not 1,
672
# because SelectFields always have an initial "blank" value.
673
if not self.blank and self.choices:
541
674
choice_list = self.get_choices_default()
542
if self.radio_admin and len(choice_list) == 1:
543
return {self.attname: choice_list[0][0]}
544
if not self.radio_admin and len(choice_list) == 2:
545
return {self.attname: choice_list[1][0]}
546
return Field.flatten_data(self, follow, obj)
675
if len(choice_list) == 2:
676
return smart_unicode(choice_list[1][0])
677
return Field.value_to_string(self, obj)
548
679
def contribute_to_class(self, cls, name):
549
680
super(ForeignKey, self).contribute_to_class(cls, name)
550
681
setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self))
682
if isinstance(self.rel.to, basestring):
685
target = self.rel.to._meta.db_table
686
cls._meta.duplicate_targets[self.column] = (target, "o2m")
552
688
def contribute_to_related_class(self, cls, related):
553
689
setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
555
691
def formfield(self, **kwargs):
556
defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
693
'form_class': forms.ModelChoiceField,
694
'queryset': self.rel.to._default_manager.complex_filter(
695
self.rel.limit_choices_to),
696
'to_field_name': self.rel.field_name,
557
698
defaults.update(kwargs)
558
return forms.ModelChoiceField(**defaults)
560
class OneToOneField(RelatedField, IntegerField):
699
return super(ForeignKey, self).formfield(**defaults)
702
# The database column type of a ForeignKey is the column type
703
# of the field to which it points. An exception is if the ForeignKey
704
# points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField,
705
# in which case the column type is simply that of an IntegerField.
706
# If the database needs similar types for key fields however, the only
707
# thing we can do is making AutoField an IntegerField.
708
rel_field = self.rel.get_related_field()
709
if (isinstance(rel_field, AutoField) or
710
(not connection.features.related_fields_match_type and
711
isinstance(rel_field, (PositiveIntegerField,
712
PositiveSmallIntegerField)))):
713
return IntegerField().db_type()
714
return rel_field.db_type()
716
class OneToOneField(ForeignKey):
718
A OneToOneField is essentially the same as a ForeignKey, with the exception
719
that always carries a "unique" constraint with it and the reverse relation
720
always returns the object pointed to (since there will only ever be one),
721
rather than returning a list.
561
723
def __init__(self, to, to_field=None, **kwargs):
563
to_name = to._meta.object_name.lower()
564
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
565
assert isinstance(to, basestring), "OneToOneField(%r) is invalid. First parameter to OneToOneField must be either a model, a model name, or the string %r" % (to, RECURSIVE_RELATIONSHIP_CONSTANT)
567
to_field = to_field or to._meta.pk.name
568
kwargs['verbose_name'] = kwargs.get('verbose_name', '')
570
if kwargs.has_key('edit_inline_type'):
572
warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
573
kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
575
kwargs['rel'] = OneToOneRel(to, to_field,
576
num_in_admin=kwargs.pop('num_in_admin', 0),
577
edit_inline=kwargs.pop('edit_inline', False),
578
related_name=kwargs.pop('related_name', None),
579
limit_choices_to=kwargs.pop('limit_choices_to', None),
580
lookup_overrides=kwargs.pop('lookup_overrides', None),
581
raw_id_admin=kwargs.pop('raw_id_admin', False))
582
kwargs['primary_key'] = True
583
IntegerField.__init__(self, **kwargs)
587
def get_attname(self):
588
return '%s_id' % self.name
590
def get_validator_unique_lookup_type(self):
591
return '%s__%s__exact' % (self.name, self.rel.get_related_field().name)
593
# TODO: Copied from ForeignKey... putting this in RelatedField adversely affects
594
# ManyToManyField. This works for now.
595
def prepare_field_objs_and_params(self, manipulator, name_prefix):
596
params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname}
597
if self.rel.raw_id_admin:
598
field_objs = self.get_manipulator_field_objs()
599
params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator))
602
field_objs = [oldforms.RadioSelectField]
603
params['ul_class'] = get_ul_class(self.radio_admin)
606
field_objs = [oldforms.NullSelectField]
608
field_objs = [oldforms.SelectField]
609
params['choices'] = self.get_choices_default()
610
return field_objs, params
612
def contribute_to_class(self, cls, name):
613
super(OneToOneField, self).contribute_to_class(cls, name)
614
setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self))
724
kwargs['unique'] = True
725
super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs)
616
727
def contribute_to_related_class(self, cls, related):
617
setattr(cls, related.get_accessor_name(), SingleRelatedObjectDescriptor(related))
728
setattr(cls, related.get_accessor_name(),
729
SingleRelatedObjectDescriptor(related))
618
730
if not cls._meta.one_to_one_field:
619
731
cls._meta.one_to_one_field = self
621
733
def formfield(self, **kwargs):
622
defaults = {'queryset': self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
623
defaults.update(kwargs)
624
return forms.ModelChoiceField(**defaults)
734
if self.rel.parent_link:
736
return super(OneToOneField, self).formfield(**kwargs)
626
738
class ManyToManyField(RelatedField, Field):
627
739
def __init__(self, to, **kwargs):
741
assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name)
742
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
743
assert isinstance(to, basestring), "%s(%r) is invalid. First parameter to ManyToManyField must be either a model, a model name, or the string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
628
745
kwargs['verbose_name'] = kwargs.get('verbose_name', None)
629
746
kwargs['rel'] = ManyToManyRel(to,
630
num_in_admin=kwargs.pop('num_in_admin', 0),
631
747
related_name=kwargs.pop('related_name', None),
632
filter_interface=kwargs.pop('filter_interface', None),
633
748
limit_choices_to=kwargs.pop('limit_choices_to', None),
634
raw_id_admin=kwargs.pop('raw_id_admin', False),
635
symmetrical=kwargs.pop('symmetrical', True))
749
symmetrical=kwargs.pop('symmetrical', True),
750
through=kwargs.pop('through', None))
636
752
self.db_table = kwargs.pop('db_table', None)
637
if kwargs["rel"].raw_id_admin:
638
kwargs.setdefault("validator_list", []).append(self.isValidIDList)
753
if kwargs['rel'].through is not None:
754
self.creates_table = False
755
assert self.db_table is None, "Cannot specify a db_table if an intermediary model is used."
757
self.creates_table = True
639
759
Field.__init__(self, **kwargs)
641
if self.rel.raw_id_admin:
642
msg = gettext_lazy('Separate multiple IDs with commas.')
644
msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
761
msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.')
645
762
self.help_text = string_concat(self.help_text, ' ', msg)
647
def get_manipulator_field_objs(self):
648
if self.rel.raw_id_admin:
649
return [oldforms.RawIdAdminField]
651
choices = self.get_choices_default()
652
return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
654
764
def get_choices_default(self):
655
765
return Field.get_choices(self, include_blank=False)
657
767
def _get_m2m_db_table(self, opts):
658
768
"Function that can be curried to provide the m2m table name for this relation"
769
if self.rel.through is not None:
770
return self.rel.through_model._meta.db_table
660
772
return self.db_table
662
774
return '%s_%s' % (opts.db_table, self.name)
664
776
def _get_m2m_column_name(self, related):
665
777
"Function that can be curried to provide the source column name for the m2m table"
666
# If this is an m2m relation to self, avoid the inevitable name clash
667
if related.model == related.parent_model:
668
return 'from_' + related.model._meta.object_name.lower() + '_id'
670
return related.model._meta.object_name.lower() + '_id'
779
return self._m2m_column_name_cache
781
if self.rel.through is not None:
782
for f in self.rel.through_model._meta.fields:
783
if hasattr(f,'rel') and f.rel and f.rel.to == related.model:
784
self._m2m_column_name_cache = f.column
786
# If this is an m2m relation to self, avoid the inevitable name clash
787
elif related.model == related.parent_model:
788
self._m2m_column_name_cache = 'from_' + related.model._meta.object_name.lower() + '_id'
790
self._m2m_column_name_cache = related.model._meta.object_name.lower() + '_id'
792
# Return the newly cached value
793
return self._m2m_column_name_cache
672
795
def _get_m2m_reverse_name(self, related):
673
796
"Function that can be curried to provide the related column name for the m2m table"
674
# If this is an m2m relation to self, avoid the inevitable name clash
675
if related.model == related.parent_model:
676
return 'to_' + related.parent_model._meta.object_name.lower() + '_id'
678
return related.parent_model._meta.object_name.lower() + '_id'
798
return self._m2m_reverse_name_cache
800
if self.rel.through is not None:
802
for f in self.rel.through_model._meta.fields:
803
if hasattr(f,'rel') and f.rel and f.rel.to == related.parent_model:
804
if related.model == related.parent_model:
805
# If this is an m2m-intermediate to self,
806
# the first foreign key you find will be
807
# the source column. Keep searching for
808
# the second foreign key.
810
self._m2m_reverse_name_cache = f.column
815
self._m2m_reverse_name_cache = f.column
817
# If this is an m2m relation to self, avoid the inevitable name clash
818
elif related.model == related.parent_model:
819
self._m2m_reverse_name_cache = 'to_' + related.parent_model._meta.object_name.lower() + '_id'
821
self._m2m_reverse_name_cache = related.parent_model._meta.object_name.lower() + '_id'
823
# Return the newly cached value
824
return self._m2m_reverse_name_cache
680
826
def isValidIDList(self, field_data, all_data):
681
827
"Validates that the value is a valid list of foreign keys"
737
907
"Returns the value of this field in the given model instance."
738
908
return getattr(obj, self.attname).all()
910
def save_form_data(self, instance, data):
911
setattr(instance, self.attname, data)
740
913
def formfield(self, **kwargs):
914
defaults = {'form_class': forms.ModelMultipleChoiceField, 'queryset': self.rel.to._default_manager.complex_filter(self.rel.limit_choices_to)}
915
defaults.update(kwargs)
741
916
# If initial is passed in, it's a list of related objects, but the
742
917
# MultipleChoiceField takes a list of IDs.
743
if kwargs.get('initial') is not None:
744
kwargs['initial'] = [i._get_pk_val() for i in kwargs['initial']]
745
defaults = {'queryset' : self.rel.to._default_manager.all(), 'required': not self.blank, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
746
defaults.update(kwargs)
747
return forms.ModelMultipleChoiceField(**defaults)
749
class ManyToOneRel(object):
750
def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None,
751
max_num_in_admin=None, num_extra_on_change=1, edit_inline=False,
752
related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False):
755
except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT
756
assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT
757
self.to, self.field_name = to, field_name
758
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
759
self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin
760
self.num_extra_on_change, self.related_name = num_extra_on_change, related_name
761
if limit_choices_to is None:
762
limit_choices_to = {}
763
self.limit_choices_to = limit_choices_to
764
self.lookup_overrides = lookup_overrides or {}
765
self.raw_id_admin = raw_id_admin
768
def get_related_field(self):
769
"Returns the Field in the 'to' object to which this relationship is tied."
770
return self.to._meta.get_field(self.field_name)
772
class OneToOneRel(ManyToOneRel):
773
def __init__(self, to, field_name, num_in_admin=0, edit_inline=False,
774
related_name=None, limit_choices_to=None, lookup_overrides=None,
776
self.to, self.field_name = to, field_name
777
self.num_in_admin, self.edit_inline = num_in_admin, edit_inline
778
self.related_name = related_name
779
if limit_choices_to is None:
780
limit_choices_to = {}
781
self.limit_choices_to = limit_choices_to
782
self.lookup_overrides = lookup_overrides or {}
783
self.raw_id_admin = raw_id_admin
784
self.multiple = False
786
class ManyToManyRel(object):
787
def __init__(self, to, num_in_admin=0, related_name=None,
788
filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True):
790
self.num_in_admin = num_in_admin
791
self.related_name = related_name
792
self.filter_interface = filter_interface
793
if limit_choices_to is None:
794
limit_choices_to = {}
795
self.limit_choices_to = limit_choices_to
796
self.edit_inline = False
797
self.raw_id_admin = raw_id_admin
798
self.symmetrical = symmetrical
801
assert not (self.raw_id_admin and self.filter_interface), "ManyToManyRels may not use both raw_id_admin and filter_interface"
918
if defaults.get('initial') is not None:
919
defaults['initial'] = [i._get_pk_val() for i in defaults['initial']]
920
return super(ManyToManyField, self).formfield(**defaults)
923
# A ManyToManyField is not represented by a single column,