diff --git a/django/db/models/base.py b/django/db/models/base.py index 3d65cc3d9dc..7bc726a617f 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -939,7 +939,7 @@ class Model(six.with_metaclass(ModelBase)): unique_checks = [] unique_togethers = [(self.__class__, self._meta.unique_together)] - for parent_class in self._meta.parents.keys(): + for parent_class in self._meta.get_parent_list(): if parent_class._meta.unique_together: unique_togethers.append((parent_class, parent_class._meta.unique_together)) @@ -959,7 +959,7 @@ class Model(six.with_metaclass(ModelBase)): # the list of checks. fields_with_class = [(self.__class__, self._meta.local_fields)] - for parent_class in self._meta.parents.keys(): + for parent_class in self._meta.get_parent_list(): fields_with_class.append((parent_class, parent_class._meta.local_fields)) for model_class, fields in fields_with_class: diff --git a/tests/model_inheritance/models.py b/tests/model_inheritance/models.py index 3245c712322..af28159757d 100644 --- a/tests/model_inheritance/models.py +++ b/tests/model_inheritance/models.py @@ -186,3 +186,24 @@ class Base(models.Model): class SubBase(Base): sub_id = models.IntegerField(primary_key=True) + + +class GrandParent(models.Model): + first_name = models.CharField(max_length=80) + last_name = models.CharField(max_length=80) + email = models.EmailField(unique=True) + + class Meta: + unique_together = ('first_name', 'last_name') + + +class Parent(GrandParent): + pass + + +class Child(Parent): + pass + + +class GrandChild(Child): + pass diff --git a/tests/model_inheritance/tests.py b/tests/model_inheritance/tests.py index 10721a6b3f5..7ee7e19a125 100644 --- a/tests/model_inheritance/tests.py +++ b/tests/model_inheritance/tests.py @@ -2,7 +2,7 @@ from __future__ import unicode_literals from operator import attrgetter -from django.core.exceptions import FieldError +from django.core.exceptions import FieldError, ValidationError from django.core.management import call_command from django.db import connection from django.test import TestCase, TransactionTestCase @@ -12,7 +12,7 @@ from django.utils import six from .models import ( Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, Post, Restaurant, Student, Supplier, Worker, MixinModel, - Title, Copy, Base, SubBase) + Title, Copy, Base, SubBase, GrandParent, GrandChild) class ModelInheritanceTests(TestCase): @@ -423,3 +423,33 @@ class InheritanceSameModelNameTests(TransactionTestCase): def test_related_name_attribute_exists(self): # The Post model doesn't have an attribute called 'attached_%(app_label)s_%(class)s_set'. self.assertFalse(hasattr(self.title, 'attached_%(app_label)s_%(class)s_set')) + + +class InheritanceUniqueTests(TestCase): + @classmethod + def setUpTestData(cls): + cls.grand_parent = GrandParent.objects.create( + email='grand_parent@example.com', + first_name='grand', + last_name='parent', + ) + + def test_unique(self): + grand_child = GrandChild( + email=self.grand_parent.email, + first_name='grand', + last_name='child', + ) + msg = 'Grand parent with this Email already exists.' + with self.assertRaisesMessage(ValidationError, msg): + grand_child.validate_unique() + + def test_unique_together(self): + grand_child = GrandChild( + email='grand_child@example.com', + first_name=self.grand_parent.first_name, + last_name=self.grand_parent.last_name, + ) + msg = 'Grand parent with this First name and Last name already exists.' + with self.assertRaisesMessage(ValidationError, msg): + grand_child.validate_unique()