Changeset 7142
- Timestamp:
- 02/21/08 22:58:28 (6 months ago)
- Files:
-
- django/branches/queryset-refactor/django/db/models/base.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/fields/related.py (modified) (5 diffs)
- django/branches/queryset-refactor/django/db/models/options.py (modified) (2 diffs)
- django/branches/queryset-refactor/docs/model-api.txt (modified) (3 diffs)
- django/branches/queryset-refactor/tests/modeltests/model_inheritance/models.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/django/db/models/base.py
r7141 r7142 60 60 new_class._meta.get_latest_by = base_meta.get_latest_by 61 61 62 # Do the appropriate setup for any model parents.63 abstract_parents = []64 for base in parents:65 if not hasattr(base, '_meta'):66 # Things without _meta aren't functional models, so they're67 # uninteresting parents.68 continue69 if not base._meta.abstract:70 attr_name = '%s_ptr' % base._meta.module_name71 field = OneToOneField(base, name=attr_name, auto_created=True)72 new_class.add_to_class(attr_name, field)73 new_class._meta.parents[base] = field74 else:75 abstract_parents.append(base)76 77 62 if getattr(new_class, '_default_manager', None) is not None: 78 63 # We have a parent who set the default manager. We need to override … … 94 79 new_class.add_to_class(obj_name, obj) 95 80 96 for parent in abstract_parents: 97 names = [f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many] 98 for field in parent._meta.local_fields: 99 if field.name in names: 100 raise TypeError('Local field %r in class %r clashes with field of similar name from abstract base class %r' 101 % (field.name, name, parent.__name__)) 102 new_class.add_to_class(field.name, field) 81 # Do the appropriate setup for any model parents. 82 o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields 83 if isinstance(f, OneToOneField)]) 84 for base in parents: 85 if not hasattr(base, '_meta'): 86 # Things without _meta aren't functional models, so they're 87 # uninteresting parents. 88 continue 89 if not base._meta.abstract: 90 if base in o2o_map: 91 field = o2o_map[base] 92 field.primary_key = True 93 new_class._meta.setup_pk(field) 94 else: 95 attr_name = '%s_ptr' % base._meta.module_name 96 field = OneToOneField(base, name=attr_name, 97 auto_created=True, parent_link=True) 98 new_class.add_to_class(attr_name, field) 99 new_class._meta.parents[base] = field 100 else: 101 names = [f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many] 102 for field in base._meta.local_fields: 103 if field.name in names: 104 raise TypeError('Local field %r in class %r clashes with field of similar name from abstract base class %r' 105 % (field.name, name, base.__name__)) 106 new_class.add_to_class(field.name, field) 103 107 104 108 if abstract: django/branches/queryset-refactor/django/db/models/fields/related.py
r7126 r7142 462 462 class ManyToOneRel(object): 463 463 def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, 464 max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, 465 related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False): 464 max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, 465 related_name=None, limit_choices_to=None, lookup_overrides=None, 466 raw_id_admin=False, parent_link=False): 466 467 try: 467 468 to._meta … … 478 479 self.raw_id_admin = raw_id_admin 479 480 self.multiple = True 481 self.parent_link = parent_link 480 482 481 483 def get_related_field(self): … … 490 492 max_num_in_admin=None, num_extra_on_change=None, edit_inline=False, 491 493 related_name=None, limit_choices_to=None, lookup_overrides=None, 492 raw_id_admin=False ):494 raw_id_admin=False, parent_link=False): 493 495 # NOTE: *_num_in_admin and num_extra_on_change are intentionally 494 496 # ignored here. We accept them as parameters only to match the calling … … 497 499 edit_inline=edit_inline, related_name=related_name, 498 500 limit_choices_to=limit_choices_to, 499 lookup_overrides=lookup_overrides, raw_id_admin=raw_id_admin) 501 lookup_overrides=lookup_overrides, raw_id_admin=raw_id_admin, 502 parent_link=parent_link) 500 503 self.multiple = False 501 504 … … 542 545 limit_choices_to=kwargs.pop('limit_choices_to', None), 543 546 lookup_overrides=kwargs.pop('lookup_overrides', None), 544 raw_id_admin=kwargs.pop('raw_id_admin', False)) 547 raw_id_admin=kwargs.pop('raw_id_admin', False), 548 parent_link=kwargs.pop('parent_link', False)) 545 549 Field.__init__(self, **kwargs) 546 550 django/branches/queryset-refactor/django/db/models/options.py
r7141 r7142 114 114 if field.rel and isinstance(field.rel, ManyToManyRel): 115 115 self.local_many_to_many.insert(bisect(self.local_many_to_many, field), field) 116 if hasattr(self, '_m2m_cache'): 117 del self._m2m_cache 116 118 else: 117 119 self.local_fields.insert(bisect(self.local_fields, field), field) 118 if not self.pk and field.primary_key: 119 self.pk = field 120 field.serialize = False 121 122 # All of these internal caches need to be updated the next time they 123 # are used. 124 # TODO: Do this more neatly. (Also, use less caches!) 125 if hasattr(self, '_field_cache'): 126 del self._field_cache 127 if hasattr(self, '_m2m_cache'): 128 del self._m2m_cache 120 self.setup_pk(field) 121 if hasattr(self, '_field_cache'): 122 del self._field_cache 123 129 124 if hasattr(self, '_name_map'): 130 125 del self._name_map 126 127 def setup_pk(self, field): 128 if not self.pk and field.primary_key: 129 self.pk = field 130 field.serialize = False 131 131 132 132 def __repr__(self): … … 316 316 for parent in self.parents: 317 317 for obj, model in parent._meta.get_all_related_objects_with_model(): 318 if obj.field.creation_counter < 0and obj.model not in parent_list:318 if (obj.field.creation_counter < 0 or obj.field.rel.parent_link) and obj.model not in parent_list: 319 319 continue 320 320 if not model: django/branches/queryset-refactor/docs/model-api.txt
r7141 r7142 1001 1001 models can be made by using a string containing the model name. 1002 1002 1003 Finally, ``OneToOneField`` takes the following extra option: 1004 1005 ======================= ============================================================ 1006 Argument Description 1007 ======================= ============================================================ 1008 ``parent_link`` When ``True`` and used in a model inherited from 1009 another model, indicates that this field should 1010 be used as the link from the child back to the 1011 parent. See `Model inheritance`_ for more 1012 details. 1013 1014 **New in Django development version** 1015 1016 ======================= ============================================================ 1017 1003 1018 **New in Django development version:** ``OneToOneField`` classes used to 1004 1019 automatically become the primary key on a model. This is no longer true, … … 1036 1051 Here's a list of all possible ``Meta`` options. No options are required. Adding 1037 1052 ``class Meta`` to a model is completely optional. 1053 1054 ``abstract`` 1055 ------------ 1056 1057 **New in Django development version** 1058 1059 When set to ``True``, denotes this model as an abstract base class. See 1060 `Abstract base classes`_ for more details. Defaults to ``False``. 1038 1061 1039 1062 ``db_table`` … … 2193 2216 you're writing your models and pay attention to the error messages. 2194 2217 2218 Specifying the parent link field 2219 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2220 2221 As mentioned, Django will automatically create a ``OneToOneField`` linking 2222 your child class back any non-abstract parent models. If you want to control 2223 the name of the attribute linking back to the parent, you can create your own 2224 link field and pass it ``parent_link=True``. For example, to explicitly 2225 specify the field that will link ``Supplier`` to ``Place`` in the above 2226 example, you could write:: 2227 2228 class Supplier(Place): 2229 parent = models.OneToOneField(Place, parent_link=True) 2230 ... 2231 2195 2232 Multiple inheritance 2196 2233 -------------------- django/branches/queryset-refactor/tests/modeltests/model_inheritance/models.py
r7141 r7142 68 68 69 69 class ParkingLot(Place): 70 # An explicit link to the parent (we can control the attribute name). 71 parent = models.OneToOneField(Place, primary_key=True, parent_link=True) 70 72 main_site = models.ForeignKey(Place, related_name='lot') 71 73
