Browse Source

Fixed #11560 -- Allowed proxy model multiple-inheritance from the same concrete base model.

Akshesh 9 years ago
parent
commit
49f95cc0a0

+ 3 - 3
django/db/models/base.py

@@ -177,10 +177,10 @@ class ModelBase(type):
                         )
                     else:
                         continue
-                if base is not None:
-                    raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
-                else:
+                if base is None:
                     base = parent
+                elif parent._meta.concrete_model is not base._meta.concrete_model:
+                    raise TypeError("Proxy model '%s' has more than one non-abstract model base class." % name)
             if base is None:
                 raise TypeError("Proxy model '%s' has no non-abstract model base class." % name)
             new_class._meta.setup_proxy(base)

+ 3 - 0
docs/releases/1.10.txt

@@ -359,6 +359,9 @@ Models
 
 * Added the :class:`~django.db.models.functions.Cast` database function.
 
+* A proxy model may now inherit multiple proxy models that share a common
+  non-abstract parent class.
+
 Requests and Responses
 ~~~~~~~~~~~~~~~~~~~~~~
 

+ 7 - 1
docs/topics/db/models.txt

@@ -1230,7 +1230,13 @@ A proxy model must inherit from exactly one non-abstract model class. You
 can't inherit from multiple non-abstract models as the proxy model doesn't
 provide any connection between the rows in the different database tables. A
 proxy model can inherit from any number of abstract model classes, providing
-they do *not* define any model fields.
+they do *not* define any model fields. A proxy model may also inherit from any
+number of proxy models that share a common non-abstract parent class.
+
+.. versionchanged:: 1.10
+
+    In earlier versions, a proxy model couldn't inherit more than one proxy
+    model that shared the same parent class.
 
 Proxy model managers
 ~~~~~~~~~~~~~~~~~~~~

+ 10 - 0
tests/proxy_models/models.py

@@ -110,10 +110,20 @@ class UserProxy(User):
         proxy = True
 
 
+class AnotherUserProxy(User):
+    class Meta:
+        proxy = True
+
+
 class UserProxyProxy(UserProxy):
     class Meta:
         proxy = True
 
+
+class MultiUserProxy(UserProxy, AnotherUserProxy):
+    class Meta:
+        proxy = True
+
 # We can still use `select_related()` to include related models in our querysets.
 
 

+ 6 - 4
tests/proxy_models/tests.py

@@ -13,9 +13,9 @@ from django.urls import reverse
 from .admin import admin as force_admin_model_registration  # NOQA
 from .models import (
     Abstract, BaseUser, Bug, Country, Improvement, Issue, LowerStatusPerson,
-    MyPerson, MyPersonProxy, OtherPerson, Person, ProxyBug, ProxyImprovement,
-    ProxyProxyBug, ProxyTrackerUser, State, StateProxy, StatusPerson,
-    TrackerUser, User, UserProxy, UserProxyProxy,
+    MultiUserProxy, MyPerson, MyPersonProxy, OtherPerson, Person, ProxyBug,
+    ProxyImprovement, ProxyProxyBug, ProxyTrackerUser, State, StateProxy,
+    StatusPerson, TrackerUser, User, UserProxy, UserProxyProxy,
 )
 
 
@@ -246,7 +246,7 @@ class ProxyModelTests(TestCase):
         ctype = ContentType.objects.get_for_model
         self.assertIs(ctype(Person), ctype(OtherPerson))
 
-    def test_user_userproxy_userproxyproxy(self):
+    def test_user_proxy_models(self):
         User.objects.create(name='Bruce')
 
         resp = [u.name for u in User.objects.all()]
@@ -258,6 +258,8 @@ class ProxyModelTests(TestCase):
         resp = [u.name for u in UserProxyProxy.objects.all()]
         self.assertEqual(resp, ['Bruce'])
 
+        self.assertEqual([u.name for u in MultiUserProxy.objects.all()], ['Bruce'])
+
     def test_proxy_for_model(self):
         self.assertEqual(UserProxy, UserProxyProxy._meta.proxy_for_model)