diff options
| author | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-09-02 15:26:00 +0000 |
|---|---|---|
| committer | Jacob Kaplan-Moss <jacob@jacobian.org> | 2008-09-02 15:26:00 +0000 |
| commit | 79d2ee3b6d405674a2a49f0884312a8cdc82d809 (patch) | |
| tree | fbb5bdc0b773664b2518c15b33f5341d7fec633c /django/db/models/base.py | |
| parent | 98e1cc92f47cbda977a923b9ba8d980bc01cd749 (diff) | |
Fixed #8309: subclasses now inherit `GenericForeignKey` correctly. There's also now an internal API so that other "virtual fields" like GFK can be inherited as well. Thanks, msaelices.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8855 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/models/base.py')
| -rw-r--r-- | django/db/models/base.py | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py index 121626ca93..e23369bb67 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -87,6 +87,14 @@ class ModelBase(type): # Things without _meta aren't functional models, so they're # uninteresting parents. continue + + # All the fields of any type declared on this model + new_fields = new_class._meta.local_fields + \ + new_class._meta.many_to_many + \ + new_class._meta.virtual_fields + field_names = set([f.name for f in new_fields]) + + # Concrete classes... if not base._meta.abstract: if base in o2o_map: field = o2o_map[base] @@ -98,13 +106,17 @@ class ModelBase(type): auto_created=True, parent_link=True) new_class.add_to_class(attr_name, field) new_class._meta.parents[base] = field + + # .. and abstract ones. else: - # The abstract base class case. - names = set([f.name for f in new_class._meta.local_fields + new_class._meta.many_to_many]) - for field in base._meta.local_fields + base._meta.local_many_to_many: - if field.name in names: - raise FieldError('Local field %r in class %r clashes with field of similar name from abstract base class %r' - % (field.name, name, base.__name__)) + # Check for clashes between locally declared fields and those on the ABC. + parent_fields = base._meta.local_fields + base._meta.local_many_to_many + for field in parent_fields: + if field.name in field_names: + raise FieldError('Local field %r in class %r clashes '\ + 'with field of similar name from '\ + 'abstract base class %r' % \ + (field.name, name, base.__name__)) new_class.add_to_class(field.name, copy.deepcopy(field)) # Inherit managers from the abstract base classes. @@ -115,6 +127,16 @@ class ModelBase(type): if not val or val is manager: new_manager = manager._copy_to_model(new_class) new_class.add_to_class(mgr_name, new_manager) + + # Inherit virtual fields (like GenericForeignKey) from the parent class + for field in base._meta.virtual_fields: + if base._meta.abstract and field.name in field_names: + raise FieldError('Local field %r in class %r clashes '\ + 'with field of similar name from '\ + 'abstract base class %r' % \ + (field.name, name, base.__name__)) + new_class.add_to_class(field.name, copy.deepcopy(field)) + if abstract: # Abstract base models can't be instantiated and don't appear in # the list of models for an app. We do the final setup for them a |
