~ubuntu-branches/ubuntu/jaunty/python-django/jaunty

« back to all changes in this revision

Viewing changes to django/db/models/fields/related.py

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant, Eddy Mulyono
  • Date: 2008-09-16 12:18:47 UTC
  • mfrom: (1.1.5 upstream) (4.1.1 lenny)
  • Revision ID: james.westby@ubuntu.com-20080916121847-mg225rg5mnsdqzr0
Tags: 1.0-1ubuntu1
* Merge from Debian (LP: #264191), remaining changes:
  - Run test suite on build.

[Eddy Mulyono]
* Update patch to workaround network test case failures.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
12
 
 
13
 
# For Python 2.3
14
 
if not hasattr(__builtins__, 'set'):
15
 
    from sets import Set as set
16
 
 
17
 
# Values for Relation.edit_inline.
18
 
TABULAR, STACKED = 1, 2
 
10
from django.core import exceptions
 
11
from django import forms
 
12
 
 
13
try:
 
14
    set
 
15
except NameError:
 
16
    from sets import Set as set   # Python 2.3 fallback
19
17
 
20
18
RECURSIVE_RELATIONSHIP_CONSTANT = 'self'
21
19
 
22
20
pending_lookups = {}
23
21
 
24
 
def add_lookup(rel_cls, field):
25
 
    name = field.rel.to
26
 
    module = rel_cls.__module__
27
 
    key = (module, name)
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):
 
23
    """
 
24
    Adds a lookup on ``cls`` when a related field is defined using a string,
 
25
    i.e.::
 
26
 
 
27
        class MyModel(Model):
 
28
            fk = ForeignKey("AnotherModel")
 
29
 
 
30
    This string can be:
 
31
 
 
32
        * RECURSIVE_RELATIONSHIP_CONSTANT (i.e. "self") to indicate a recursive
 
33
          relation.
 
34
 
 
35
        * The name of a model (i.e "AnotherModel") to indicate another model in
 
36
          the same app.
 
37
 
 
38
        * An app-label and model name (i.e. "someapp.AnotherModel") to indicate
 
39
          another model in a different app.
 
40
 
 
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.
 
44
 
 
45
    operation is the work that must be performed once the relation can be resolved.
 
46
    """
 
47
    # Check for recursive relations
 
48
    if relation == RECURSIVE_RELATIONSHIP_CONSTANT:
 
49
        app_label = cls._meta.app_label
 
50
        model_name = cls.__name__
 
51
 
 
52
    else:
 
53
        # Look for an "app.Model" relation
 
54
        try:
 
55
            app_label, model_name = relation.split(".")
 
56
        except ValueError:
 
57
            # If we can't split, assume a model in current app
 
58
            app_label = cls._meta.app_label
 
59
            model_name = relation
 
60
 
 
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
 
64
    # is prepared.
 
65
    model = get_model(app_label, model_name, False)
31
66
    if model:
32
 
        field.rel.to = model
33
 
        field.do_related_class(model, rel_cls)
 
67
        operation(field, model, cls)
34
68
    else:
35
 
        # Mark the related field for later lookup
36
 
        pending_lookups.setdefault(key, []).append((rel_cls, field))
37
 
 
38
 
def do_pending_lookups(sender):
39
 
    other_cls = 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)
44
 
 
45
 
dispatcher.connect(do_pending_lookups, signal=signals.class_prepared)
46
 
 
47
 
def manipulator_valid_rel_key(f, self, field_data, all_data):
48
 
    "Validates that the value is a valid foreign key"
49
 
    klass = f.rel.to
50
 
    try:
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)
 
72
 
 
73
def do_pending_lookups(sender, **kwargs):
 
74
    """
 
75
    Handle any pending relations to the sending model. Sent from class_prepared.
 
76
    """
 
77
    key = (sender._meta.app_label, sender.__name__)
 
78
    for cls, field, operation in pending_lookups.pop(key, []):
 
79
        operation(field, sender, cls)
 
80
 
 
81
signals.class_prepared.connect(do_pending_lookups)
54
82
 
55
83
#HACK
56
84
class RelatedField(object):
62
90
 
63
91
        if hasattr(sup, 'contribute_to_class'):
64
92
            sup.contribute_to_class(cls, name)
 
93
 
 
94
        if not cls._meta.abstract and self.rel.related_name:
 
95
            self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()}
 
96
 
65
97
        other = self.rel.to
66
98
        if isinstance(other, basestring):
67
 
            if other == RECURSIVE_RELATIONSHIP_CONSTANT:
68
 
                self.rel.to = cls.__name__
69
 
            add_lookup(cls, self)
 
99
            def resolve_related_class(field, model, cls):
 
100
                field.rel.to = model
 
101
                field.do_related_class(model, cls)
 
102
            add_lazy_relation(cls, self, other, resolve_related_class)
70
103
        else:
71
104
            self.do_related_class(other, cls)
72
105
 
73
106
    def set_attributes_from_rel(self):
74
107
        self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name)
75
 
        self.verbose_name = self.verbose_name or self.rel.to._meta.verbose_name
 
108
        if self.verbose_name is None:
 
109
            self.verbose_name = self.rel.to._meta.verbose_name
76
110
        self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name
77
111
 
78
112
    def do_related_class(self, other, cls):
79
113
        self.set_attributes_from_rel()
80
114
        related = RelatedObject(other, cls, self)
81
 
        self.contribute_to_related_class(other, related)
 
115
        if not cls._meta.abstract:
 
116
            self.contribute_to_related_class(other, related)
82
117
 
83
118
    def get_db_prep_lookup(self, lookup_type, value):
84
119
        # If we are doing a lookup on a Related Field, we must be
90
125
            # that object. In certain conditions (especially one-to-one relations),
91
126
            # the primary key may itself be an object - so we need to keep drilling
92
127
            # down until we hit a value that can be used for a comparison.
93
 
            v = value
 
128
            v, field = value, None
94
129
            try:
95
130
                while True:
96
 
                    v = getattr(v, v._meta.pk.name)
 
131
                    v, field = getattr(v, v._meta.pk.name), v._meta.pk
97
132
            except AttributeError:
98
133
                pass
 
134
            if field:
 
135
                if lookup_type in ('range', 'in'):
 
136
                    v = [v]
 
137
                v = field.get_db_prep_lookup(lookup_type, v)
 
138
                if isinstance(v, list):
 
139
                    v = v[0]
99
140
            return v
100
141
 
101
 
        if lookup_type == 'exact':
 
142
        if hasattr(value, 'as_sql'):
 
143
            sql, params = value.as_sql()
 
144
            return QueryWrapper(('(%s)' % sql), params)
 
145
 
 
146
        # FIXME: lt and gt are explicitally allowed to make
 
147
        # get_(next/prev)_by_date work; other lookups are not allowed since that
 
148
        # gets messy pretty quick. This is a good candidate for some refactoring
 
149
        # in the future.
 
150
        if lookup_type in ['exact', 'gt', 'lt']:
102
151
            return [pk_trace(value)]
103
 
        if lookup_type == 'in':
 
152
        if lookup_type in ('range', 'in'):
104
153
            return [pk_trace(v) for v in value]
105
154
        elif lookup_type == 'isnull':
106
155
            return []
107
156
        raise TypeError, "Related Field has invalid lookup: %s" % lookup_type
108
157
 
109
158
    def _get_related_query_name(self, opts):
110
 
        # This method defines the name that can be used to identify this related object
111
 
        # in a table-spanning query. It uses the lower-cased object_name by default,
112
 
        # but this can be overridden with the "related_name" option.
 
159
        # This method defines the name that can be used to identify this
 
160
        # related object in a table-spanning query. It uses the lower-cased
 
161
        # object_name by default, but this can be overridden with the
 
162
        # "related_name" option.
113
163
        return self.rel.related_name or opts.object_name.lower()
114
164
 
115
165
class SingleRelatedObjectDescriptor(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()
123
174
 
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
127
178
 
128
 
        params = {'%s__pk' % self.related.field.name: instance._get_pk_val()}
129
 
        rel_obj = self.related.model._default_manager.get(**params)
130
 
        return rel_obj
 
179
        try:
 
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)
 
185
            return rel_obj
131
186
 
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
 
190
 
 
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.
 
194
 
 
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))
 
204
 
135
205
        # Set the value of the related field
136
206
        setattr(value, self.related.field.rel.get_related_field().attname, instance)
137
207
 
138
 
        # Clear the cache, if it exists
139
 
        try:
140
 
            delattr(value, self.related.field.get_cache_name())
141
 
        except AttributeError:
142
 
            pass
 
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)
143
213
 
144
214
class ReverseSingleRelatedObjectDescriptor(object):
145
215
    # This class provides the functionality that makes the related-object
168
238
                params = {'%s__pk' % self.field.rel.field_name: val}
169
239
            else:
170
240
                params = {'%s__exact' % self.field.rel.field_name: val}
171
 
            rel_obj = self.field.rel.to._default_manager.get(**params)
 
241
 
 
242
            # If the related manager indicates that it should be used for
 
243
            # related fields, respect that.
 
244
            rel_mgr = self.field.rel.to._default_manager
 
245
            if getattr(rel_mgr, 'use_for_related_fields', False):
 
246
                rel_obj = rel_mgr.get(**params)
 
247
            else:
 
248
                rel_obj = QuerySet(self.field.rel.to).get(**params)
172
249
            setattr(instance, cache_name, rel_obj)
173
250
            return rel_obj
174
251
 
175
252
    def __set__(self, instance, value):
176
253
        if instance is None:
177
254
            raise AttributeError, "%s must be accessed via instance" % self._field.name
 
255
 
 
256
        # If null=True, we can assign null here, but otherwise the value needs
 
257
        # to be an instance of the related class.
 
258
        if value is None and self.field.null == False:
 
259
            raise ValueError('Cannot assign None: "%s.%s" does not allow null values.' %
 
260
                                (instance._meta.object_name, self.field.name))
 
261
        elif value is not None and not isinstance(value, self.field.rel.to):
 
262
            raise ValueError('Cannot assign "%r": "%s.%s" must be a "%s" instance.' %
 
263
                                (value, instance._meta.object_name,
 
264
                                 self.field.name, self.field.rel.to._meta.object_name))
 
265
 
178
266
        # Set the value of the related field
179
267
        try:
180
268
            val = getattr(value, self.field.rel.get_related_field().attname)
182
270
            val = None
183
271
        setattr(instance, self.field.attname, val)
184
272
 
185
 
        # Clear the cache, if it exists
186
 
        try:
187
 
            delattr(instance, self.field.get_cache_name())
188
 
        except AttributeError:
189
 
            pass
 
273
        # Since we already know what the related object is, seed the related
 
274
        # object cache now, too. This avoids another db hit if you get the
 
275
        # object you just set.
 
276
        setattr(instance, self.field.get_cache_name(), value)
190
277
 
191
278
class ForeignRelatedObjectsDescriptor(object):
192
279
    # This class provides the functionality that makes the related-object
219
306
            add.alters_data = True
220
307
 
221
308
            def create(self, **kwargs):
222
 
                new_obj = self.model(**kwargs)
223
 
                self.add(new_obj)
224
 
                return new_obj
 
309
                kwargs.update({rel_field.name: instance})
 
310
                return super(RelatedManager, self).create(**kwargs)
225
311
            create.alters_data = True
226
312
 
 
313
            def get_or_create(self, **kwargs):
 
314
                # Update kwargs with the related object that this
 
315
                # ForeignRelatedObjectsDescriptor knows about.
 
316
                kwargs.update({rel_field.name: instance})
 
317
                return super(RelatedManager, self).get_or_create(**kwargs)
 
318
            get_or_create.alters_data = True
 
319
 
227
320
            # remove() and clear() are only provided if the ForeignKey can have a value of null.
228
321
            if rel_field.null:
229
322
                def remove(self, *objs):
244
337
                clear.alters_data = True
245
338
 
246
339
        manager = RelatedManager()
247
 
        manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
 
340
        attname = rel_field.rel.get_related_field().name
 
341
        manager.core_filters = {'%s__%s' % (rel_field.name, attname):
 
342
                getattr(instance, attname)}
248
343
        manager.model = self.related.model
249
344
 
250
345
        return manager
260
355
            manager.clear()
261
356
        manager.add(*value)
262
357
 
263
 
def create_many_related_manager(superclass):
 
358
def create_many_related_manager(superclass, through=False):
264
359
    """Creates a manager that subclasses 'superclass' (which is a Manager)
265
360
    and adds behavior for many-to-many related objects."""
266
361
    class ManyRelatedManager(superclass):
274
369
            self.join_table = join_table
275
370
            self.source_col_name = source_col_name
276
371
            self.target_col_name = target_col_name
 
372
            self.through = through
277
373
            self._pk_val = self.instance._get_pk_val()
278
374
            if self._pk_val is None:
279
 
                raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % model)
 
375
                raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
280
376
 
281
377
        def get_query_set(self):
282
 
            return superclass.get_query_set(self).filter(**(self.core_filters))
283
 
 
284
 
        def add(self, *objs):
285
 
            self._add_items(self.source_col_name, self.target_col_name, *objs)
286
 
 
287
 
            # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table
288
 
            if self.symmetrical:
289
 
                self._add_items(self.target_col_name, self.source_col_name, *objs)
290
 
        add.alters_data = True
291
 
 
292
 
        def remove(self, *objs):
293
 
            self._remove_items(self.source_col_name, self.target_col_name, *objs)
294
 
 
295
 
            # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table
296
 
            if self.symmetrical:
297
 
                self._remove_items(self.target_col_name, self.source_col_name, *objs)
298
 
        remove.alters_data = True
 
378
            return superclass.get_query_set(self)._next_is_sticky().filter(**(self.core_filters))
 
379
 
 
380
        # If the ManyToMany relation has an intermediary model,
 
381
        # the add and remove methods do not exist.
 
382
        if through is None:
 
383
            def add(self, *objs):
 
384
                self._add_items(self.source_col_name, self.target_col_name, *objs)
 
385
 
 
386
                # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table
 
387
                if self.symmetrical:
 
388
                    self._add_items(self.target_col_name, self.source_col_name, *objs)
 
389
            add.alters_data = True
 
390
 
 
391
            def remove(self, *objs):
 
392
                self._remove_items(self.source_col_name, self.target_col_name, *objs)
 
393
 
 
394
                # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table
 
395
                if self.symmetrical:
 
396
                    self._remove_items(self.target_col_name, self.source_col_name, *objs)
 
397
            remove.alters_data = True
299
398
 
300
399
        def clear(self):
301
400
            self._clear_items(self.source_col_name)
306
405
        clear.alters_data = True
307
406
 
308
407
        def create(self, **kwargs):
309
 
            new_obj = self.model(**kwargs)
310
 
            new_obj.save()
 
408
            # This check needs to be done here, since we can't later remove this
 
409
            # from the method lookup table, as we do with add and remove.
 
410
            if through is not None:
 
411
                raise AttributeError, "Cannot use create() on a ManyToManyField which specifies an intermediary model. Use %s's Manager instead." % through
 
412
            new_obj = super(ManyRelatedManager, self).create(**kwargs)
311
413
            self.add(new_obj)
312
414
            return new_obj
313
415
        create.alters_data = True
314
416
 
 
417
        def get_or_create(self, **kwargs):
 
418
            obj, created = \
 
419
                    super(ManyRelatedManager, self).get_or_create(**kwargs)
 
420
            # We only need to add() if created because if we got an object back
 
421
            # from get() then the relationship already exists.
 
422
            if created:
 
423
                self.add(obj)
 
424
            return obj, created
 
425
        get_or_create.alters_data = True
 
426
 
315
427
        def _add_items(self, source_col_name, target_col_name, *objs):
316
428
            # join_table: name of the m2m link table
317
429
            # source_col_name: the PK colname in join_table for the source object
318
430
            # target_col_name: the PK colname in join_table for the target object
319
431
            # *objs - objects to add. Either object instances, or primary keys of object instances.
320
 
            from django.db import connection
321
432
 
322
433
            # If there aren't any objects, there is nothing to do.
323
434
            if objs:
335
446
                    (target_col_name, self.join_table, source_col_name,
336
447
                    target_col_name, ",".join(['%s'] * len(new_ids))),
337
448
                    [self._pk_val] + list(new_ids))
338
 
                if cursor.rowcount is not None and cursor.rowcount != 0:
339
 
                    existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)])
340
 
                else:
341
 
                    existing_ids = set()
 
449
                existing_ids = set([row[0] for row in cursor.fetchall()])
342
450
 
343
451
                # Add the ones that aren't there already
344
452
                for obj_id in (new_ids - existing_ids):
351
459
            # source_col_name: the PK colname in join_table for the source object
352
460
            # target_col_name: the PK colname in join_table for the target object
353
461
            # *objs - objects to remove
354
 
            from django.db import connection
355
462
 
356
463
            # If there aren't any objects, there is nothing to do.
357
464
            if objs:
372
479
 
373
480
        def _clear_items(self, source_col_name):
374
481
            # source_col_name: the PK colname in join_table for the source object
375
 
            from django.db import connection
376
482
            cursor = connection.cursor()
377
483
            cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
378
484
                (self.join_table, source_col_name),
399
505
        # model's default manager.
400
506
        rel_model = self.related.model
401
507
        superclass = rel_model._default_manager.__class__
402
 
        RelatedManager = create_many_related_manager(superclass)
 
508
        RelatedManager = create_many_related_manager(superclass, self.related.field.rel.through)
403
509
 
404
 
        qn = backend.quote_name
 
510
        qn = connection.ops.quote_name
405
511
        manager = RelatedManager(
406
512
            model=rel_model,
407
513
            core_filters={'%s__pk' % self.related.field.name: instance._get_pk_val()},
418
524
        if instance is None:
419
525
            raise AttributeError, "Manager must be accessed via instance"
420
526
 
 
527
        through = getattr(self.related.field.rel, 'through', None)
 
528
        if through is not None:
 
529
            raise AttributeError, "Cannot set values on a ManyToManyField which specifies an intermediary model. Use %s's Manager instead." % through
 
530
 
421
531
        manager = self.__get__(instance)
422
532
        manager.clear()
423
533
        manager.add(*value)
440
550
        # model's default manager.
441
551
        rel_model=self.field.rel.to
442
552
        superclass = rel_model._default_manager.__class__
443
 
        RelatedManager = create_many_related_manager(superclass)
 
553
        RelatedManager = create_many_related_manager(superclass, self.field.rel.through)
444
554
 
445
 
        qn = backend.quote_name
 
555
        qn = connection.ops.quote_name
446
556
        manager = RelatedManager(
447
557
            model=rel_model,
448
558
            core_filters={'%s__pk' % self.field.related_query_name(): instance._get_pk_val()},
459
569
        if instance is None:
460
570
            raise AttributeError, "Manager must be accessed via instance"
461
571
 
 
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
 
575
 
462
576
        manager = self.__get__(instance)
463
577
        manager.clear()
464
578
        manager.add(*value)
465
579
 
 
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):
 
583
        try:
 
584
            to._meta
 
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 {}
 
593
        self.multiple = True
 
594
        self.parent_link = parent_link
 
595
 
 
596
    def get_related_field(self):
 
597
        """
 
598
        Returns the Field in the 'to' object to which this relationship is
 
599
        tied.
 
600
        """
 
601
        data = self.to._meta.get_field_by_name(self.field_name)
 
602
        if not data[2]:
 
603
            raise FieldDoesNotExist("No related field named '%s'" %
 
604
                    self.field_name)
 
605
        return data[0]
 
606
 
 
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
 
614
 
 
615
class ManyToManyRel(object):
 
616
    def __init__(self, to, related_name=None, limit_choices_to=None,
 
617
            symmetrical=True, through=None):
 
618
        self.to = to
 
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
 
624
        self.multiple = True
 
625
        self.through = through
 
626
 
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):
469
630
        try:
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)
473
634
        else:
 
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', '')
476
 
 
477
 
        if kwargs.has_key('edit_inline_type'):
478
 
            import warnings
479
 
            warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
480
 
            kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
481
 
 
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)
 
638
 
 
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)
493
645
 
494
646
        self.db_index = True
499
651
    def get_validator_unique_lookup_type(self):
500
652
        return '%s__%s__exact' % (self.name, self.rel.get_related_field().name)
501
653
 
502
 
    def prepare_field_objs_and_params(self, manipulator, name_prefix):
503
 
        params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname}
504
 
        if self.rel.raw_id_admin:
505
 
            field_objs = self.get_manipulator_field_objs()
506
 
            params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator))
507
 
        else:
508
 
            if self.radio_admin:
509
 
                field_objs = [oldforms.RadioSelectField]
510
 
                params['ul_class'] = get_ul_class(self.radio_admin)
511
 
            else:
512
 
                if self.null:
513
 
                    field_objs = [oldforms.NullSelectField]
514
 
                else:
515
 
                    field_objs = [oldforms.SelectField]
516
 
            params['choices'] = self.get_choices_default()
517
 
        return field_objs, params
518
 
 
519
 
    def get_manipulator_field_objs(self):
520
 
        rel_field = self.rel.get_related_field()
521
 
        if self.rel.raw_id_admin and not isinstance(rel_field, AutoField):
522
 
            return rel_field.get_manipulator_field_objs()
523
 
        else:
524
 
            return [oldforms.IntegerField]
 
654
    def get_default(self):
 
655
        "Here we check if the default value is an object and return the to_field if so."
 
656
        field_default = super(ForeignKey, self).get_default()
 
657
        if isinstance(field_default, self.rel.to):
 
658
            return getattr(field_default, self.rel.get_related_field().attname)
 
659
        return field_default
525
660
 
526
661
    def get_db_prep_save(self, value):
527
662
        if value == '' or value == None:
529
664
        else:
530
665
            return self.rel.get_related_field().get_db_prep_save(value)
531
666
 
532
 
    def flatten_data(self, follow, obj=None):
 
667
    def value_to_string(self, obj):
533
668
        if not 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
539
 
            # length is 1.
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)
547
678
 
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):
 
683
            target = self.rel.to
 
684
        else:
 
685
            target = self.rel.to._meta.db_table
 
686
        cls._meta.duplicate_targets[self.column] = (target, "o2m")
551
687
 
552
688
    def contribute_to_related_class(self, cls, related):
553
689
        setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related))
554
690
 
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}
 
692
        defaults = {
 
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,
 
697
        }
557
698
        defaults.update(kwargs)
558
 
        return forms.ModelChoiceField(**defaults)
559
 
 
560
 
class OneToOneField(RelatedField, IntegerField):
 
699
        return super(ForeignKey, self).formfield(**defaults)
 
700
 
 
701
    def db_type(self):
 
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()
 
715
 
 
716
class OneToOneField(ForeignKey):
 
717
    """
 
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.
 
722
    """
561
723
    def __init__(self, to, to_field=None, **kwargs):
562
 
        try:
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)
566
 
        else:
567
 
            to_field = to_field or to._meta.pk.name
568
 
        kwargs['verbose_name'] = kwargs.get('verbose_name', '')
569
 
 
570
 
        if kwargs.has_key('edit_inline_type'):
571
 
            import warnings
572
 
            warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.")
573
 
            kwargs['edit_inline'] = kwargs.pop('edit_inline_type')
574
 
 
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)
584
 
 
585
 
        self.db_index = True
586
 
 
587
 
    def get_attname(self):
588
 
        return '%s_id' % self.name
589
 
 
590
 
    def get_validator_unique_lookup_type(self):
591
 
        return '%s__%s__exact' % (self.name, self.rel.get_related_field().name)
592
 
 
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))
600
 
        else:
601
 
            if self.radio_admin:
602
 
                field_objs = [oldforms.RadioSelectField]
603
 
                params['ul_class'] = get_ul_class(self.radio_admin)
604
 
            else:
605
 
                if self.null:
606
 
                    field_objs = [oldforms.NullSelectField]
607
 
                else:
608
 
                    field_objs = [oldforms.SelectField]
609
 
            params['choices'] = self.get_choices_default()
610
 
        return field_objs, params
611
 
 
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)
615
726
 
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
620
732
 
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:
 
735
            return None
 
736
        return super(OneToOneField, self).formfield(**kwargs)
625
737
 
626
738
class ManyToManyField(RelatedField, Field):
627
739
    def __init__(self, to, **kwargs):
 
740
        try:
 
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)
 
744
 
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))
 
751
 
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."
 
756
        else:
 
757
            self.creates_table = True
 
758
 
639
759
        Field.__init__(self, **kwargs)
640
760
 
641
 
        if self.rel.raw_id_admin:
642
 
            msg = gettext_lazy('Separate multiple IDs with commas.')
643
 
        else:
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)
646
763
 
647
 
    def get_manipulator_field_objs(self):
648
 
        if self.rel.raw_id_admin:
649
 
            return [oldforms.RawIdAdminField]
650
 
        else:
651
 
            choices = self.get_choices_default()
652
 
            return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)]
653
 
 
654
764
    def get_choices_default(self):
655
765
        return Field.get_choices(self, include_blank=False)
656
766
 
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"
659
 
        if self.db_table:
 
769
        if self.rel.through is not None:
 
770
            return self.rel.through_model._meta.db_table
 
771
        elif self.db_table:
660
772
            return self.db_table
661
773
        else:
662
774
            return '%s_%s' % (opts.db_table, self.name)
663
775
 
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'
669
 
        else:
670
 
            return related.model._meta.object_name.lower() + '_id'
 
778
        try:
 
779
            return self._m2m_column_name_cache
 
780
        except:
 
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
 
785
                        break
 
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'
 
789
            else:
 
790
                self._m2m_column_name_cache = related.model._meta.object_name.lower() + '_id'
 
791
 
 
792
            # Return the newly cached value
 
793
            return self._m2m_column_name_cache
671
794
 
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'
677
 
        else:
678
 
            return related.parent_model._meta.object_name.lower() + '_id'
 
797
        try:
 
798
            return self._m2m_reverse_name_cache
 
799
        except:
 
800
            if self.rel.through is not None:
 
801
                found = False
 
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.
 
809
                            if found:
 
810
                                self._m2m_reverse_name_cache = f.column
 
811
                                break
 
812
                            else:
 
813
                                found = True
 
814
                        else:
 
815
                            self._m2m_reverse_name_cache = f.column
 
816
                            break
 
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'
 
820
            else:
 
821
                self._m2m_reverse_name_cache = related.parent_model._meta.object_name.lower() + '_id'
 
822
 
 
823
            # Return the newly cached value
 
824
            return self._m2m_reverse_name_cache
679
825
 
680
826
    def isValidIDList(self, field_data, all_data):
681
827
        "Validates that the value is a valid list of foreign keys"
688
834
        objects = mod._default_manager.in_bulk(pks)
689
835
        if len(objects) != len(pks):
690
836
            badkeys = [k for k in pks if k not in objects]
691
 
            raise validators.ValidationError, ngettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",
692
 
                    "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % {
 
837
            raise exceptions.ValidationError(
 
838
                ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.",
 
839
                          "Please enter valid %(self)s IDs. The values %(value)r are invalid.",
 
840
                          len(badkeys)) % {
693
841
                'self': self.verbose_name,
694
842
                'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys),
695
 
            }
 
843
            })
696
844
 
697
 
    def flatten_data(self, follow, obj = None):
698
 
        new_data = {}
 
845
    def value_to_string(self, obj):
 
846
        data = ''
699
847
        if obj:
700
 
            instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()]
701
 
            if self.rel.raw_id_admin:
702
 
                new_data[self.name] = ",".join([str(id) for id in instance_ids])
703
 
            else:
704
 
                new_data[self.name] = instance_ids
 
848
            qs = getattr(obj, self.name).all()
 
849
            data = [instance._get_pk_val() for instance in qs]
705
850
        else:
706
851
            # In required many-to-many fields with only one available choice,
707
852
            # select that one available choice.
708
 
            if not self.blank and not self.rel.edit_inline and not self.rel.raw_id_admin:
 
853
            if not self.blank:
709
854
                choices_list = self.get_choices_default()
710
855
                if len(choices_list) == 1:
711
 
                    new_data[self.name] = [choices_list[0][0]]
712
 
        return new_data
 
856
                    data = [choices_list[0][0]]
 
857
        return smart_unicode(data)
713
858
 
714
859
    def contribute_to_class(self, cls, name):
 
860
        # To support multiple relations to self, it's useful to have a non-None
 
861
        # related name on symmetrical relations for internal reasons. The
 
862
        # concept doesn't make a lot of sense externally ("you want me to
 
863
        # specify *what* on my non-reversible relation?!"), so we set it up
 
864
        # automatically. The funky name reduces the chance of an accidental
 
865
        # clash.
 
866
        if self.rel.symmetrical and self.rel.to == "self" and self.rel.related_name is None:
 
867
            self.rel.related_name = "%s_rel_+" % name
 
868
 
715
869
        super(ManyToManyField, self).contribute_to_class(cls, name)
716
870
        # Add the descriptor for the m2m relation
717
871
        setattr(cls, self.name, ReverseManyRelatedObjectsDescriptor(self))
719
873
        # Set up the accessor for the m2m table name for the relation
720
874
        self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta)
721
875
 
 
876
        # Populate some necessary rel arguments so that cross-app relations
 
877
        # work correctly.
 
878
        if isinstance(self.rel.through, basestring):
 
879
            def resolve_through_model(field, model, cls):
 
880
                field.rel.through_model = model
 
881
            add_lazy_relation(cls, self, self.rel.through, resolve_through_model)
 
882
        elif self.rel.through:
 
883
            self.rel.through_model = self.rel.through
 
884
            self.rel.through = self.rel.through._meta.object_name
 
885
 
 
886
        if isinstance(self.rel.to, basestring):
 
887
            target = self.rel.to
 
888
        else:
 
889
            target = self.rel.to._meta.db_table
 
890
        cls._meta.duplicate_targets[self.column] = (target, "m2m")
 
891
 
722
892
    def contribute_to_related_class(self, cls, related):
723
893
        # m2m relations to self do not have a ManyRelatedObjectsDescriptor,
724
894
        # as it would be redundant - unless the field is non-symmetrical.
737
907
        "Returns the value of this field in the given model instance."
738
908
        return getattr(obj, self.attname).all()
739
909
 
 
910
    def save_form_data(self, instance, data):
 
911
        setattr(instance, self.attname, data)
 
912
 
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)
748
 
 
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):
753
 
        try:
754
 
            to._meta
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
766
 
        self.multiple = True
767
 
 
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)
771
 
 
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,
775
 
        raw_id_admin=False):
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
785
 
 
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):
789
 
        self.to = to
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
799
 
        self.multiple = True
800
 
 
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)
 
921
 
 
922
    def db_type(self):
 
923
        # A ManyToManyField is not represented by a single column,
 
924
        # so return None.
 
925
        return None
 
926