Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

[1.0.X] Made it explicit if you accidentally override a Field from a …

…parent model.

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.

Backport of r9974 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9975 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 79f53b4f206f82847b645e36263e3537ebbae7b1 1 parent 182301c
Malcolm Tredinnick authored March 04, 2009
22  django/db/models/base.py
@@ -94,6 +94,16 @@ def __new__(cls, name, bases, attrs):
94 94
                          new_class._meta.virtual_fields
95 95
             field_names = set([f.name for f in new_fields])
96 96
 
  97
+            parent_fields = base._meta.local_fields + base._meta.local_many_to_many
  98
+            # Check for clashes between locally declared fields and those
  99
+            # on the base classes (we cannot handle shadowed fields at the
  100
+            # moment).
  101
+            for field in parent_fields:
  102
+                if field.name in field_names:
  103
+                    raise FieldError('Local field %r in class %r clashes '
  104
+                                     'with field of similar name from '
  105
+                                     'base class %r' %
  106
+                                        (field.name, name, base.__name__))
97 107
             if not base._meta.abstract:
98 108
                 # Concrete classes...
99 109
                 if base in o2o_map:
@@ -107,16 +117,7 @@ def __new__(cls, name, bases, attrs):
107 117
 
108 118
             else:
109 119
                 # .. and abstract ones.
110  
-
111  
-                # Check for clashes between locally declared fields and those
112  
-                # on the ABC.
113  
-                parent_fields = base._meta.local_fields + base._meta.local_many_to_many
114 120
                 for field in parent_fields:
115  
-                    if field.name in field_names:
116  
-                        raise FieldError('Local field %r in class %r clashes '\
117  
-                                         'with field of similar name from '\
118  
-                                         'abstract base class %r' % \
119  
-                                            (field.name, name, base.__name__))
120 121
                     new_class.add_to_class(field.name, copy.deepcopy(field))
121 122
 
122 123
                 # Pass any non-abstract parent classes onto child.
@@ -131,7 +132,8 @@ def __new__(cls, name, bases, attrs):
131 132
                     new_manager = manager._copy_to_model(new_class)
132 133
                     new_class.add_to_class(mgr_name, new_manager)
133 134
 
134  
-            # Inherit virtual fields (like GenericForeignKey) from the parent class
  135
+            # Inherit virtual fields (like GenericForeignKey) from the parent
  136
+            # class
135 137
             for field in base._meta.virtual_fields:
136 138
                 if base._meta.abstract and field.name in field_names:
137 139
                     raise FieldError('Local field %r in class %r clashes '\
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
1006 1006
 inheritance hierarchies as simple and straightforward as possible so that you
1007 1007
 won't have to struggle to work out where a particular piece of information is
1008 1008
 coming from.
  1009
+
  1010
+Field name "hiding" is not permitted
  1011
+-------------------------------------
  1012
+
  1013
+In normal Python class inheritance, it is permissible for a child class to
  1014
+override any attribute from the parent class. In Django, this is not permitted
  1015
+for attributes that are :class:`~django.db.models.fields.Field` instances (at
  1016
+least, not at the moment). If a base class has a field called ``author``, you
  1017
+cannot create another model field called ``author`` in any class that inherits
  1018
+from that base class.
  1019
+
  1020
+Overriding fields in a parent model leads to difficulties in areas such as
  1021
+initialising new instances (specifying which field is being intialised in
  1022
+``Model.__init__``) and serialization. These are features which normal Python
  1023
+class inheritance doesn't have to deal with in quite the same way, so the
  1024
+difference between Django model inheritance and Python class inheritance isn't
  1025
+merely arbitrary.
  1026
+
  1027
+This restriction only applies to attributes which are
  1028
+:class:`~django.db.models.fields.Field` instances. Normal Python attributes
  1029
+can be overridden if you wish. It also only applies to the name of the
  1030
+attribute as Python sees it: if you are manually specifying the database
  1031
+column name, you can have the same column name appearing in both a child and
  1032
+an ancestor model for multi-table inheritance (they are columns in two
  1033
+different database tables).
  1034
+
  1035
+Django will raise a ``FieldError`` exception if you override any model field
  1036
+in any ancestor model.
  1037
+

0 notes on commit 79f53b4

Please sign in to comment.
Something went wrong with that request. Please try again.