Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Made it explicit if you accidentally override a Field from a parent m…

…odel.

This was always not working reliably (model initialization and serialization
were two of the problems). Now, it's an explicit error. Also, documented.

Fixed #10252.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@9974 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 7197a4dcb7de7085e04f1b4edfb31eacb7dd885c 1 parent f9c8eeb
@malcolmt malcolmt authored
Showing with 41 additions and 10 deletions.
  1. +12 −10 django/db/models/base.py
  2. +29 −0 docs/topics/db/models.txt
View
22 django/db/models/base.py
@@ -94,6 +94,16 @@ def __new__(cls, name, bases, attrs):
new_class._meta.virtual_fields
field_names = set([f.name for f in new_fields])
+ parent_fields = base._meta.local_fields + base._meta.local_many_to_many
+ # Check for clashes between locally declared fields and those
+ # on the base classes (we cannot handle shadowed fields at the
+ # moment).
+ 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 '
+ 'base class %r' %
+ (field.name, name, base.__name__))
if not base._meta.abstract:
# Concrete classes...
if base in o2o_map:
@@ -107,16 +117,7 @@ def __new__(cls, name, bases, attrs):
else:
# .. and abstract ones.
-
- # 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))
# Pass any non-abstract parent classes onto child.
@@ -131,7 +132,8 @@ def __new__(cls, name, bases, attrs):
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
+ # 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 '\
View
29 docs/topics/db/models.txt
@@ -1006,3 +1006,32 @@ field or method to every class that inherits the mix-in. Try to keep your
inheritance hierarchies as simple and straightforward as possible so that you
won't have to struggle to work out where a particular piece of information is
coming from.
+
+Field name "hiding" is not permitted
+-------------------------------------
+
+In normal Python class inheritance, it is permissible for a child class to
+override any attribute from the parent class. In Django, this is not permitted
+for attributes that are :class:`~django.db.models.fields.Field` instances (at
+least, not at the moment). If a base class has a field called ``author``, you
+cannot create another model field called ``author`` in any class that inherits
+from that base class.
+
+Overriding fields in a parent model leads to difficulties in areas such as
+initialising new instances (specifying which field is being intialised in
+``Model.__init__``) and serialization. These are features which normal Python
+class inheritance doesn't have to deal with in quite the same way, so the
+difference between Django model inheritance and Python class inheritance isn't
+merely arbitrary.
+
+This restriction only applies to attributes which are
+:class:`~django.db.models.fields.Field` instances. Normal Python attributes
+can be overridden if you wish. It also only applies to the name of the
+attribute as Python sees it: if you are manually specifying the database
+column name, you can have the same column name appearing in both a child and
+an ancestor model for multi-table inheritance (they are columns in two
+different database tables).
+
+Django will raise a ``FieldError`` exception if you override any model field
+in any ancestor model.
+
Please sign in to comment.
Something went wrong with that request. Please try again.