Răsfoiți Sursa

Fixed #14217 -- Added validation for field name collision when using model inheritance.

sarthakmeh 9 ani în urmă
părinte
comite
4bc00defd0
3 a modificat fișierele cu 27 adăugiri și 1 ștergeri
  1. 1 0
      AUTHORS
  2. 7 1
      django/db/models/base.py
  3. 19 0
      tests/invalid_models_tests/test_models.py

+ 1 - 0
AUTHORS

@@ -629,6 +629,7 @@ answer newbie questions, and generally made Django that much better:
     Ryan Niemeyer <https://profiles.google.com/ryan.niemeyer/about>
     Sam Newman <http://www.magpiebrain.com/>
     Sander Dijkhuis <sander.dijkhuis@gmail.com>
+    Sarthak Mehrish <sarthakmeh03@gmail.com>
     schwank@gmail.com
     Scot Hacker <shacker@birdhouse.org>
     Scott Barr <scott@divisionbyzero.com.au>

+ 7 - 1
django/db/models/base.py

@@ -1334,7 +1334,13 @@ class Model(six.with_metaclass(ModelBase)):
                 used_fields[f.attname] = f
 
         # Check that fields defined in the model don't clash with fields from
-        # parents.
+        # parents, including auto-generated fields like multi-table inheritance
+        # child accessors.
+        for parent in cls._meta.get_parent_list():
+            for f in parent._meta.get_fields():
+                if f not in used_fields:
+                    used_fields[f.name] = f
+
         for f in cls._meta.local_fields:
             clash = used_fields.get(f.name) or used_fields.get(f.attname) or None
             # Note that we may detect clash between user-defined non-unique

+ 19 - 0
tests/invalid_models_tests/test_models.py

@@ -436,6 +436,25 @@ class FieldNamesTests(IsolatedModelsTestCase):
 
 class ShadowingFieldsTests(IsolatedModelsTestCase):
 
+    def test_field_name_clash_with_child_accessor(self):
+        class Parent(models.Model):
+            pass
+
+        class Child(Parent):
+            child = models.CharField(max_length=100)
+
+        errors = Child.check()
+        expected = [
+            Error(
+                "The field 'child' clashes with the field "
+                "'child' from model 'invalid_models_tests.parent'.",
+                hint=None,
+                obj=Child._meta.get_field('child'),
+                id='models.E006',
+            )
+        ]
+        self.assertEqual(errors, expected)
+
     def test_multiinheritance_clash(self):
         class Mother(models.Model):
             clash = models.IntegerField()