101 # Add an accessor to allow easy determination of the related query path for this field |
88 # Add an accessor to allow easy determination of the related query path for this field |
102 self.related_query_name = curry(self._get_related_query_name, cls._meta) |
89 self.related_query_name = curry(self._get_related_query_name, cls._meta) |
103 |
90 |
104 if hasattr(sup, 'contribute_to_class'): |
91 if hasattr(sup, 'contribute_to_class'): |
105 sup.contribute_to_class(cls, name) |
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 |
106 other = self.rel.to |
97 other = self.rel.to |
107 if isinstance(other, basestring): |
98 if isinstance(other, basestring): |
108 add_lazy_relation(cls, self, other) |
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) |
109 else: |
103 else: |
110 self.do_related_class(other, cls) |
104 self.do_related_class(other, cls) |
111 if not cls._meta.abstract and self.rel.related_name: |
|
112 self.rel.related_name = self.rel.related_name % {'class': cls.__name__.lower()} |
|
113 |
105 |
114 def set_attributes_from_rel(self): |
106 def set_attributes_from_rel(self): |
115 self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name) |
107 self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name) |
116 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 |
117 self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name |
110 self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name |
118 |
111 |
119 def do_related_class(self, other, cls): |
112 def do_related_class(self, other, cls): |
120 self.set_attributes_from_rel() |
113 self.set_attributes_from_rel() |
121 related = RelatedObject(other, cls, self) |
114 related = RelatedObject(other, cls, self) |
122 self.contribute_to_related_class(other, related) |
115 if not cls._meta.abstract: |
|
116 self.contribute_to_related_class(other, related) |
123 |
117 |
124 def get_db_prep_lookup(self, lookup_type, value): |
118 def get_db_prep_lookup(self, lookup_type, value): |
125 # If we are doing a lookup on a Related Field, we must be |
119 # If we are doing a lookup on a Related Field, we must be |
126 # comparing object instances. The value should be the PK of value, |
120 # comparing object instances. The value should be the PK of value, |
127 # not value itself. |
121 # not value itself. |
216 other_field = self.field.rel.get_related_field() |
236 other_field = self.field.rel.get_related_field() |
217 if other_field.rel: |
237 if other_field.rel: |
218 params = {'%s__pk' % self.field.rel.field_name: val} |
238 params = {'%s__pk' % self.field.rel.field_name: val} |
219 else: |
239 else: |
220 params = {'%s__exact' % self.field.rel.field_name: val} |
240 params = {'%s__exact' % self.field.rel.field_name: val} |
221 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) |
222 setattr(instance, cache_name, rel_obj) |
249 setattr(instance, cache_name, rel_obj) |
223 return rel_obj |
250 return rel_obj |
224 |
251 |
225 def __set__(self, instance, value): |
252 def __set__(self, instance, value): |
226 if instance is None: |
253 if instance is None: |
227 raise AttributeError, "%s must be accessed via instance" % self._field.name |
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 |
228 # Set the value of the related field |
266 # Set the value of the related field |
229 try: |
267 try: |
230 val = getattr(value, self.field.rel.get_related_field().attname) |
268 val = getattr(value, self.field.rel.get_related_field().attname) |
231 except AttributeError: |
269 except AttributeError: |
232 val = None |
270 val = None |
233 setattr(instance, self.field.attname, val) |
271 setattr(instance, self.field.attname, val) |
234 |
272 |
235 # Clear the cache, if it exists |
273 # Since we already know what the related object is, seed the related |
236 try: |
274 # object cache now, too. This avoids another db hit if you get the |
237 delattr(instance, self.field.get_cache_name()) |
275 # object you just set. |
238 except AttributeError: |
276 setattr(instance, self.field.get_cache_name(), value) |
239 pass |
|
240 |
277 |
241 class ForeignRelatedObjectsDescriptor(object): |
278 class ForeignRelatedObjectsDescriptor(object): |
242 # This class provides the functionality that makes the related-object |
279 # This class provides the functionality that makes the related-object |
243 # managers available as attributes on a model class, for fields that have |
280 # managers available as attributes on a model class, for fields that have |
244 # multiple "remote" values and have a ForeignKey pointed at them by |
281 # multiple "remote" values and have a ForeignKey pointed at them by |
322 self.symmetrical = symmetrical |
367 self.symmetrical = symmetrical |
323 self.instance = instance |
368 self.instance = instance |
324 self.join_table = join_table |
369 self.join_table = join_table |
325 self.source_col_name = source_col_name |
370 self.source_col_name = source_col_name |
326 self.target_col_name = target_col_name |
371 self.target_col_name = target_col_name |
|
372 self.through = through |
327 self._pk_val = self.instance._get_pk_val() |
373 self._pk_val = self.instance._get_pk_val() |
328 if self._pk_val is None: |
374 if self._pk_val is None: |
329 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__) |
330 |
376 |
331 def get_query_set(self): |
377 def get_query_set(self): |
332 return superclass.get_query_set(self).filter(**(self.core_filters)) |
378 return superclass.get_query_set(self)._next_is_sticky().filter(**(self.core_filters)) |
333 |
379 |
334 def add(self, *objs): |
380 # If the ManyToMany relation has an intermediary model, |
335 self._add_items(self.source_col_name, self.target_col_name, *objs) |
381 # the add and remove methods do not exist. |
336 |
382 if through is None: |
337 # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table |
383 def add(self, *objs): |
338 if self.symmetrical: |
384 self._add_items(self.source_col_name, self.target_col_name, *objs) |
339 self._add_items(self.target_col_name, self.source_col_name, *objs) |
385 |
340 add.alters_data = True |
386 # If this is a symmetrical m2m relation to self, add the mirror entry in the m2m table |
341 |
387 if self.symmetrical: |
342 def remove(self, *objs): |
388 self._add_items(self.target_col_name, self.source_col_name, *objs) |
343 self._remove_items(self.source_col_name, self.target_col_name, *objs) |
389 add.alters_data = True |
344 |
390 |
345 # If this is a symmetrical m2m relation to self, remove the mirror entry in the m2m table |
391 def remove(self, *objs): |
346 if self.symmetrical: |
392 self._remove_items(self.source_col_name, self.target_col_name, *objs) |
347 self._remove_items(self.target_col_name, self.source_col_name, *objs) |
393 |
348 remove.alters_data = True |
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 |
349 |
398 |
350 def clear(self): |
399 def clear(self): |
351 self._clear_items(self.source_col_name) |
400 self._clear_items(self.source_col_name) |
352 |
401 |
353 # If this is a symmetrical m2m relation to self, clear the mirror entry in the m2m table |
402 # If this is a symmetrical m2m relation to self, clear the mirror entry in the m2m table |
354 if self.symmetrical: |
403 if self.symmetrical: |
355 self._clear_items(self.target_col_name) |
404 self._clear_items(self.target_col_name) |
356 clear.alters_data = True |
405 clear.alters_data = True |
357 |
406 |
358 def create(self, **kwargs): |
407 def create(self, **kwargs): |
359 new_obj = self.model(**kwargs) |
408 # This check needs to be done here, since we can't later remove this |
360 new_obj.save() |
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) |
361 self.add(new_obj) |
413 self.add(new_obj) |
362 return new_obj |
414 return new_obj |
363 create.alters_data = True |
415 create.alters_data = True |
|
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 |
364 |
426 |
365 def _add_items(self, source_col_name, target_col_name, *objs): |
427 def _add_items(self, source_col_name, target_col_name, *objs): |
366 # join_table: name of the m2m link table |
428 # join_table: name of the m2m link table |
367 # source_col_name: the PK colname in join_table for the source object |
429 # source_col_name: the PK colname in join_table for the source object |
368 # target_col_name: the PK colname in join_table for the target object |
430 # target_col_name: the PK colname in join_table for the target object |
501 |
567 |
502 def __set__(self, instance, value): |
568 def __set__(self, instance, value): |
503 if instance is None: |
569 if instance is None: |
504 raise AttributeError, "Manager must be accessed via instance" |
570 raise AttributeError, "Manager must be accessed via instance" |
505 |
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 |
506 manager = self.__get__(instance) |
576 manager = self.__get__(instance) |
507 manager.clear() |
577 manager.clear() |
508 manager.add(*value) |
578 manager.add(*value) |
509 |
579 |
510 class ManyToOneRel(object): |
580 class ManyToOneRel(object): |
511 def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, |
581 def __init__(self, to, field_name, related_name=None, |
512 max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, |
582 limit_choices_to=None, lookup_overrides=None, parent_link=False): |
513 related_name=None, limit_choices_to=None, lookup_overrides=None, |
|
514 raw_id_admin=False, parent_link=False): |
|
515 try: |
583 try: |
516 to._meta |
584 to._meta |
517 except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT |
585 except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT |
518 assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT |
586 assert isinstance(to, basestring), "'to' must be either a model, a model name or the string %r" % RECURSIVE_RELATIONSHIP_CONSTANT |
519 self.to, self.field_name = to, field_name |
587 self.to, self.field_name = to, field_name |
520 self.num_in_admin, self.edit_inline = num_in_admin, edit_inline |
588 self.related_name = related_name |
521 self.min_num_in_admin, self.max_num_in_admin = min_num_in_admin, max_num_in_admin |
|
522 self.num_extra_on_change, self.related_name = num_extra_on_change, related_name |
|
523 if limit_choices_to is None: |
589 if limit_choices_to is None: |
524 limit_choices_to = {} |
590 limit_choices_to = {} |
525 self.limit_choices_to = limit_choices_to |
591 self.limit_choices_to = limit_choices_to |
526 self.lookup_overrides = lookup_overrides or {} |
592 self.lookup_overrides = lookup_overrides or {} |
527 self.raw_id_admin = raw_id_admin |
|
528 self.multiple = True |
593 self.multiple = True |
529 self.parent_link = parent_link |
594 self.parent_link = parent_link |
530 |
595 |
531 def get_related_field(self): |
596 def get_related_field(self): |
532 """ |
597 """ |
538 raise FieldDoesNotExist("No related field named '%s'" % |
603 raise FieldDoesNotExist("No related field named '%s'" % |
539 self.field_name) |
604 self.field_name) |
540 return data[0] |
605 return data[0] |
541 |
606 |
542 class OneToOneRel(ManyToOneRel): |
607 class OneToOneRel(ManyToOneRel): |
543 def __init__(self, to, field_name, num_in_admin=0, min_num_in_admin=None, |
608 def __init__(self, to, field_name, related_name=None, |
544 max_num_in_admin=None, num_extra_on_change=None, edit_inline=False, |
609 limit_choices_to=None, lookup_overrides=None, parent_link=False): |
545 related_name=None, limit_choices_to=None, lookup_overrides=None, |
610 super(OneToOneRel, self).__init__(to, field_name, |
546 raw_id_admin=False, parent_link=False): |
611 related_name=related_name, limit_choices_to=limit_choices_to, |
547 # NOTE: *_num_in_admin and num_extra_on_change are intentionally |
612 lookup_overrides=lookup_overrides, parent_link=parent_link) |
548 # ignored here. We accept them as parameters only to match the calling |
|
549 # signature of ManyToOneRel.__init__(). |
|
550 super(OneToOneRel, self).__init__(to, field_name, num_in_admin, |
|
551 edit_inline=edit_inline, related_name=related_name, |
|
552 limit_choices_to=limit_choices_to, |
|
553 lookup_overrides=lookup_overrides, raw_id_admin=raw_id_admin, |
|
554 parent_link=parent_link) |
|
555 self.multiple = False |
613 self.multiple = False |
556 |
614 |
557 class ManyToManyRel(object): |
615 class ManyToManyRel(object): |
558 def __init__(self, to, num_in_admin=0, related_name=None, |
616 def __init__(self, to, related_name=None, limit_choices_to=None, |
559 filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True): |
617 symmetrical=True, through=None): |
560 self.to = to |
618 self.to = to |
561 self.num_in_admin = num_in_admin |
|
562 self.related_name = related_name |
619 self.related_name = related_name |
563 self.filter_interface = filter_interface |
|
564 if limit_choices_to is None: |
620 if limit_choices_to is None: |
565 limit_choices_to = {} |
621 limit_choices_to = {} |
566 self.limit_choices_to = limit_choices_to |
622 self.limit_choices_to = limit_choices_to |
567 self.edit_inline = False |
|
568 self.raw_id_admin = raw_id_admin |
|
569 self.symmetrical = symmetrical |
623 self.symmetrical = symmetrical |
570 self.multiple = True |
624 self.multiple = True |
571 |
625 self.through = through |
572 assert not (self.raw_id_admin and self.filter_interface), "ManyToManyRels may not use both raw_id_admin and filter_interface" |
|
573 |
626 |
574 class ForeignKey(RelatedField, Field): |
627 class ForeignKey(RelatedField, Field): |
575 empty_strings_allowed = False |
628 empty_strings_allowed = False |
576 def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs): |
629 def __init__(self, to, to_field=None, rel_class=ManyToOneRel, **kwargs): |
577 try: |
630 try: |
578 to_name = to._meta.object_name.lower() |
631 to_name = to._meta.object_name.lower() |
579 except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT |
632 except AttributeError: # to._meta doesn't exist, so it must be RECURSIVE_RELATIONSHIP_CONSTANT |
580 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) |
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) |
581 else: |
634 else: |
|
635 assert not to._meta.abstract, "%s cannot define a relation with abstract class %s" % (self.__class__.__name__, to._meta.object_name) |
582 to_field = to_field or to._meta.pk.name |
636 to_field = to_field or to._meta.pk.name |
583 kwargs['verbose_name'] = kwargs.get('verbose_name', '') |
637 kwargs['verbose_name'] = kwargs.get('verbose_name', None) |
584 |
|
585 if 'edit_inline_type' in kwargs: |
|
586 import warnings |
|
587 warnings.warn("edit_inline_type is deprecated. Use edit_inline instead.", DeprecationWarning) |
|
588 kwargs['edit_inline'] = kwargs.pop('edit_inline_type') |
|
589 |
638 |
590 kwargs['rel'] = rel_class(to, to_field, |
639 kwargs['rel'] = rel_class(to, to_field, |
591 num_in_admin=kwargs.pop('num_in_admin', 3), |
|
592 min_num_in_admin=kwargs.pop('min_num_in_admin', None), |
|
593 max_num_in_admin=kwargs.pop('max_num_in_admin', None), |
|
594 num_extra_on_change=kwargs.pop('num_extra_on_change', 1), |
|
595 edit_inline=kwargs.pop('edit_inline', False), |
|
596 related_name=kwargs.pop('related_name', None), |
640 related_name=kwargs.pop('related_name', None), |
597 limit_choices_to=kwargs.pop('limit_choices_to', None), |
641 limit_choices_to=kwargs.pop('limit_choices_to', None), |
598 lookup_overrides=kwargs.pop('lookup_overrides', None), |
642 lookup_overrides=kwargs.pop('lookup_overrides', None), |
599 raw_id_admin=kwargs.pop('raw_id_admin', False), |
|
600 parent_link=kwargs.pop('parent_link', False)) |
643 parent_link=kwargs.pop('parent_link', False)) |
601 Field.__init__(self, **kwargs) |
644 Field.__init__(self, **kwargs) |
602 |
645 |
603 self.db_index = True |
646 self.db_index = True |
604 |
647 |
605 def get_attname(self): |
648 def get_attname(self): |
606 return '%s_id' % self.name |
649 return '%s_id' % self.name |
607 |
650 |
608 def get_validator_unique_lookup_type(self): |
651 def get_validator_unique_lookup_type(self): |
609 return '%s__%s__exact' % (self.name, self.rel.get_related_field().name) |
652 return '%s__%s__exact' % (self.name, self.rel.get_related_field().name) |
610 |
|
611 def prepare_field_objs_and_params(self, manipulator, name_prefix): |
|
612 params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname} |
|
613 if self.rel.raw_id_admin: |
|
614 field_objs = self.get_manipulator_field_objs() |
|
615 params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator)) |
|
616 else: |
|
617 if self.radio_admin: |
|
618 field_objs = [oldforms.RadioSelectField] |
|
619 params['ul_class'] = get_ul_class(self.radio_admin) |
|
620 else: |
|
621 if self.null: |
|
622 field_objs = [oldforms.NullSelectField] |
|
623 else: |
|
624 field_objs = [oldforms.SelectField] |
|
625 params['choices'] = self.get_choices_default() |
|
626 return field_objs, params |
|
627 |
653 |
628 def get_default(self): |
654 def get_default(self): |
629 "Here we check if the default value is an object and return the to_field if so." |
655 "Here we check if the default value is an object and return the to_field if so." |
630 field_default = super(ForeignKey, self).get_default() |
656 field_default = super(ForeignKey, self).get_default() |
631 if isinstance(field_default, self.rel.to): |
657 if isinstance(field_default, self.rel.to): |
632 return getattr(field_default, self.rel.get_related_field().attname) |
658 return getattr(field_default, self.rel.get_related_field().attname) |
633 return field_default |
659 return field_default |
634 |
660 |
635 def get_manipulator_field_objs(self): |
|
636 rel_field = self.rel.get_related_field() |
|
637 if self.rel.raw_id_admin and not isinstance(rel_field, AutoField): |
|
638 return rel_field.get_manipulator_field_objs() |
|
639 else: |
|
640 return [oldforms.IntegerField] |
|
641 |
|
642 def get_db_prep_save(self, value): |
661 def get_db_prep_save(self, value): |
643 if value == '' or value == None: |
662 if value == '' or value == None: |
644 return None |
663 return None |
645 else: |
664 else: |
646 return self.rel.get_related_field().get_db_prep_save(value) |
665 return self.rel.get_related_field().get_db_prep_save(value) |
647 |
666 |
648 def flatten_data(self, follow, obj=None): |
667 def value_to_string(self, obj): |
649 if not obj: |
668 if not obj: |
650 # In required many-to-one fields with only one available choice, |
669 # In required many-to-one fields with only one available choice, |
651 # select that one available choice. Note: For SelectFields |
670 # select that one available choice. Note: For SelectFields |
652 # (radio_admin=False), we have to check that the length of choices |
671 # we have to check that the length of choices is *2*, not 1, |
653 # is *2*, not 1, because SelectFields always have an initial |
672 # because SelectFields always have an initial "blank" value. |
654 # "blank" value. Otherwise (radio_admin=True), we check that the |
673 if not self.blank and self.choices: |
655 # length is 1. |
|
656 if not self.blank and (not self.rel.raw_id_admin or self.choices): |
|
657 choice_list = self.get_choices_default() |
674 choice_list = self.get_choices_default() |
658 if self.radio_admin and len(choice_list) == 1: |
675 if len(choice_list) == 2: |
659 return {self.attname: choice_list[0][0]} |
676 return smart_unicode(choice_list[1][0]) |
660 if not self.radio_admin and len(choice_list) == 2: |
677 return Field.value_to_string(self, obj) |
661 return {self.attname: choice_list[1][0]} |
|
662 return Field.flatten_data(self, follow, obj) |
|
663 |
678 |
664 def contribute_to_class(self, cls, name): |
679 def contribute_to_class(self, cls, name): |
665 super(ForeignKey, self).contribute_to_class(cls, name) |
680 super(ForeignKey, self).contribute_to_class(cls, name) |
666 setattr(cls, self.name, ReverseSingleRelatedObjectDescriptor(self)) |
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") |
667 |
687 |
668 def contribute_to_related_class(self, cls, related): |
688 def contribute_to_related_class(self, cls, related): |
669 setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related)) |
689 setattr(cls, related.get_accessor_name(), ForeignRelatedObjectsDescriptor(related)) |
670 |
690 |
671 def formfield(self, **kwargs): |
691 def formfield(self, **kwargs): |
672 defaults = {'form_class': forms.ModelChoiceField, 'queryset': self.rel.to._default_manager.all()} |
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 } |
673 defaults.update(kwargs) |
698 defaults.update(kwargs) |
674 return super(ForeignKey, self).formfield(**defaults) |
699 return super(ForeignKey, self).formfield(**defaults) |
675 |
700 |
676 def db_type(self): |
701 def db_type(self): |
677 # The database column type of a ForeignKey is the column type |
702 # The database column type of a ForeignKey is the column type |
678 # of the field to which it points. An exception is if the ForeignKey |
703 # of the field to which it points. An exception is if the ForeignKey |
679 # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField, |
704 # points to an AutoField/PositiveIntegerField/PositiveSmallIntegerField, |
680 # in which case the column type is simply that of an IntegerField. |
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. |
681 rel_field = self.rel.get_related_field() |
708 rel_field = self.rel.get_related_field() |
682 if isinstance(rel_field, (AutoField, PositiveIntegerField, PositiveSmallIntegerField)): |
709 if (isinstance(rel_field, AutoField) or |
|
710 (not connection.features.related_fields_match_type and |
|
711 isinstance(rel_field, (PositiveIntegerField, |
|
712 PositiveSmallIntegerField)))): |
683 return IntegerField().db_type() |
713 return IntegerField().db_type() |
684 return rel_field.db_type() |
714 return rel_field.db_type() |
685 |
715 |
686 class OneToOneField(ForeignKey): |
716 class OneToOneField(ForeignKey): |
687 """ |
717 """ |
690 always returns the object pointed to (since there will only ever be one), |
720 always returns the object pointed to (since there will only ever be one), |
691 rather than returning a list. |
721 rather than returning a list. |
692 """ |
722 """ |
693 def __init__(self, to, to_field=None, **kwargs): |
723 def __init__(self, to, to_field=None, **kwargs): |
694 kwargs['unique'] = True |
724 kwargs['unique'] = True |
695 if 'num_in_admin' not in kwargs: |
|
696 kwargs['num_in_admin'] = 0 |
|
697 super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs) |
725 super(OneToOneField, self).__init__(to, to_field, OneToOneRel, **kwargs) |
698 |
726 |
699 def contribute_to_related_class(self, cls, related): |
727 def contribute_to_related_class(self, cls, related): |
700 setattr(cls, related.get_accessor_name(), |
728 setattr(cls, related.get_accessor_name(), |
701 SingleRelatedObjectDescriptor(related)) |
729 SingleRelatedObjectDescriptor(related)) |
702 if not cls._meta.one_to_one_field: |
730 if not cls._meta.one_to_one_field: |
703 cls._meta.one_to_one_field = self |
731 cls._meta.one_to_one_field = self |
704 |
732 |
|
733 def formfield(self, **kwargs): |
|
734 if self.rel.parent_link: |
|
735 return None |
|
736 return super(OneToOneField, self).formfield(**kwargs) |
|
737 |
705 class ManyToManyField(RelatedField, Field): |
738 class ManyToManyField(RelatedField, Field): |
706 def __init__(self, to, **kwargs): |
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 |
707 kwargs['verbose_name'] = kwargs.get('verbose_name', None) |
745 kwargs['verbose_name'] = kwargs.get('verbose_name', None) |
708 kwargs['rel'] = ManyToManyRel(to, |
746 kwargs['rel'] = ManyToManyRel(to, |
709 num_in_admin=kwargs.pop('num_in_admin', 0), |
|
710 related_name=kwargs.pop('related_name', None), |
747 related_name=kwargs.pop('related_name', None), |
711 filter_interface=kwargs.pop('filter_interface', None), |
|
712 limit_choices_to=kwargs.pop('limit_choices_to', None), |
748 limit_choices_to=kwargs.pop('limit_choices_to', None), |
713 raw_id_admin=kwargs.pop('raw_id_admin', False), |
749 symmetrical=kwargs.pop('symmetrical', True), |
714 symmetrical=kwargs.pop('symmetrical', True)) |
750 through=kwargs.pop('through', None)) |
|
751 |
715 self.db_table = kwargs.pop('db_table', None) |
752 self.db_table = kwargs.pop('db_table', None) |
716 if kwargs["rel"].raw_id_admin: |
753 if kwargs['rel'].through is not None: |
717 kwargs.setdefault("validator_list", []).append(self.isValidIDList) |
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 |
718 Field.__init__(self, **kwargs) |
759 Field.__init__(self, **kwargs) |
719 |
760 |
720 if self.rel.raw_id_admin: |
761 msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.') |
721 msg = ugettext_lazy('Separate multiple IDs with commas.') |
|
722 else: |
|
723 msg = ugettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.') |
|
724 self.help_text = string_concat(self.help_text, ' ', msg) |
762 self.help_text = string_concat(self.help_text, ' ', msg) |
725 |
|
726 def get_manipulator_field_objs(self): |
|
727 if self.rel.raw_id_admin: |
|
728 return [oldforms.RawIdAdminField] |
|
729 else: |
|
730 choices = self.get_choices_default() |
|
731 return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)] |
|
732 |
763 |
733 def get_choices_default(self): |
764 def get_choices_default(self): |
734 return Field.get_choices(self, include_blank=False) |
765 return Field.get_choices(self, include_blank=False) |
735 |
766 |
736 def _get_m2m_db_table(self, opts): |
767 def _get_m2m_db_table(self, opts): |
737 "Function that can be curried to provide the m2m table name for this relation" |
768 "Function that can be curried to provide the m2m table name for this relation" |
738 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: |
739 return self.db_table |
772 return self.db_table |
740 else: |
773 else: |
741 return '%s_%s' % (opts.db_table, self.name) |
774 return '%s_%s' % (opts.db_table, self.name) |
742 |
775 |
743 def _get_m2m_column_name(self, related): |
776 def _get_m2m_column_name(self, related): |
744 "Function that can be curried to provide the source column name for the m2m table" |
777 "Function that can be curried to provide the source column name for the m2m table" |
745 # If this is an m2m relation to self, avoid the inevitable name clash |
778 try: |
746 if related.model == related.parent_model: |
779 return self._m2m_column_name_cache |
747 return 'from_' + related.model._meta.object_name.lower() + '_id' |
780 except: |
748 else: |
781 if self.rel.through is not None: |
749 return related.model._meta.object_name.lower() + '_id' |
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 |
750 |
794 |
751 def _get_m2m_reverse_name(self, related): |
795 def _get_m2m_reverse_name(self, related): |
752 "Function that can be curried to provide the related column name for the m2m table" |
796 "Function that can be curried to provide the related column name for the m2m table" |
753 # If this is an m2m relation to self, avoid the inevitable name clash |
797 try: |
754 if related.model == related.parent_model: |
798 return self._m2m_reverse_name_cache |
755 return 'to_' + related.parent_model._meta.object_name.lower() + '_id' |
799 except: |
756 else: |
800 if self.rel.through is not None: |
757 return related.parent_model._meta.object_name.lower() + '_id' |
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 |
758 |
825 |
759 def isValidIDList(self, field_data, all_data): |
826 def isValidIDList(self, field_data, all_data): |
760 "Validates that the value is a valid list of foreign keys" |
827 "Validates that the value is a valid list of foreign keys" |
761 mod = self.rel.to |
828 mod = self.rel.to |
762 try: |
829 try: |
765 # the CommaSeparatedIntegerField validator will catch this error |
832 # the CommaSeparatedIntegerField validator will catch this error |
766 return |
833 return |
767 objects = mod._default_manager.in_bulk(pks) |
834 objects = mod._default_manager.in_bulk(pks) |
768 if len(objects) != len(pks): |
835 if len(objects) != len(pks): |
769 badkeys = [k for k in pks if k not in objects] |
836 badkeys = [k for k in pks if k not in objects] |
770 raise validators.ValidationError, ungettext("Please enter valid %(self)s IDs. The value %(value)r is invalid.", |
837 raise exceptions.ValidationError( |
771 "Please enter valid %(self)s IDs. The values %(value)r are invalid.", len(badkeys)) % { |
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)) % { |
772 'self': self.verbose_name, |
841 'self': self.verbose_name, |
773 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys), |
842 'value': len(badkeys) == 1 and badkeys[0] or tuple(badkeys), |
774 } |
843 }) |
775 |
844 |
776 def flatten_data(self, follow, obj = None): |
845 def value_to_string(self, obj): |
777 new_data = {} |
846 data = '' |
778 if obj: |
847 if obj: |
779 instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()] |
848 qs = getattr(obj, self.name).all() |
780 if self.rel.raw_id_admin: |
849 data = [instance._get_pk_val() for instance in qs] |
781 new_data[self.name] = u",".join([smart_unicode(id) for id in instance_ids]) |
|
782 else: |
|
783 new_data[self.name] = instance_ids |
|
784 else: |
850 else: |
785 # In required many-to-many fields with only one available choice, |
851 # In required many-to-many fields with only one available choice, |
786 # select that one available choice. |
852 # select that one available choice. |
787 if not self.blank and not self.rel.edit_inline and not self.rel.raw_id_admin: |
853 if not self.blank: |
788 choices_list = self.get_choices_default() |
854 choices_list = self.get_choices_default() |
789 if len(choices_list) == 1: |
855 if len(choices_list) == 1: |
790 new_data[self.name] = [choices_list[0][0]] |
856 data = [choices_list[0][0]] |
791 return new_data |
857 return smart_unicode(data) |
792 |
858 |
793 def contribute_to_class(self, cls, name): |
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 |
794 super(ManyToManyField, self).contribute_to_class(cls, name) |
869 super(ManyToManyField, self).contribute_to_class(cls, name) |
795 # Add the descriptor for the m2m relation |
870 # Add the descriptor for the m2m relation |
796 setattr(cls, self.name, ReverseManyRelatedObjectsDescriptor(self)) |
871 setattr(cls, self.name, ReverseManyRelatedObjectsDescriptor(self)) |
797 |
872 |
798 # Set up the accessor for the m2m table name for the relation |
873 # Set up the accessor for the m2m table name for the relation |
799 self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta) |
874 self.m2m_db_table = curry(self._get_m2m_db_table, cls._meta) |
|
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") |
800 |
891 |
801 def contribute_to_related_class(self, cls, related): |
892 def contribute_to_related_class(self, cls, related): |
802 # m2m relations to self do not have a ManyRelatedObjectsDescriptor, |
893 # m2m relations to self do not have a ManyRelatedObjectsDescriptor, |
803 # as it would be redundant - unless the field is non-symmetrical. |
894 # as it would be redundant - unless the field is non-symmetrical. |
804 if related.model != related.parent_model or not self.rel.symmetrical: |
895 if related.model != related.parent_model or not self.rel.symmetrical: |