mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.8.x] Fixed #15321 -- Honored ancestors unique checks.
Thanks to Tim for the review.
Backport of 79f27f2b61 from master
			
			
This commit is contained in:
		
				
					committed by
					
						 Simon Charette
						Simon Charette
					
				
			
			
				
	
			
			
			
						parent
						
							3e24ab6f4c
						
					
				
				
					commit
					fc49e73648
				
			| @@ -939,7 +939,7 @@ class Model(six.with_metaclass(ModelBase)): | |||||||
|         unique_checks = [] |         unique_checks = [] | ||||||
|  |  | ||||||
|         unique_togethers = [(self.__class__, self._meta.unique_together)] |         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: |             if parent_class._meta.unique_together: | ||||||
|                 unique_togethers.append((parent_class, 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. |         # the list of checks. | ||||||
|  |  | ||||||
|         fields_with_class = [(self.__class__, self._meta.local_fields)] |         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)) |             fields_with_class.append((parent_class, parent_class._meta.local_fields)) | ||||||
|  |  | ||||||
|         for model_class, fields in fields_with_class: |         for model_class, fields in fields_with_class: | ||||||
|   | |||||||
| @@ -186,3 +186,24 @@ class Base(models.Model): | |||||||
|  |  | ||||||
| class SubBase(Base): | class SubBase(Base): | ||||||
|     sub_id = models.IntegerField(primary_key=True) |     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 | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ from __future__ import unicode_literals | |||||||
|  |  | ||||||
| from operator import attrgetter | 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.core.management import call_command | ||||||
| from django.db import connection | from django.db import connection | ||||||
| from django.test import TestCase, TransactionTestCase | from django.test import TestCase, TransactionTestCase | ||||||
| @@ -12,7 +12,7 @@ from django.utils import six | |||||||
| from .models import ( | from .models import ( | ||||||
|     Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, Post, |     Chef, CommonInfo, ItalianRestaurant, ParkingLot, Place, Post, | ||||||
|     Restaurant, Student, Supplier, Worker, MixinModel, |     Restaurant, Student, Supplier, Worker, MixinModel, | ||||||
|     Title, Copy, Base, SubBase) |     Title, Copy, Base, SubBase, GrandParent, GrandChild) | ||||||
|  |  | ||||||
|  |  | ||||||
| class ModelInheritanceTests(TestCase): | class ModelInheritanceTests(TestCase): | ||||||
| @@ -423,3 +423,33 @@ class InheritanceSameModelNameTests(TransactionTestCase): | |||||||
|     def test_related_name_attribute_exists(self): |     def test_related_name_attribute_exists(self): | ||||||
|         # The Post model doesn't have an attribute called 'attached_%(app_label)s_%(class)s_set'. |         # 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')) |         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() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user