Author: russellm
Date: 2008-08-19 09:17:24 -0500 (Tue, 19 Aug 2008)
New Revision: 8442

Modified:
   django/trunk/django/core/management/validation.py
   django/trunk/django/db/models/fields/related.py
   django/trunk/tests/modeltests/invalid_models/models.py
Log:
Fixed #7908: Added validation checks on attempts to create ForeignKey and M2M 
relations with abstract classes. Thanks to Rock Howard for the report.

Modified: django/trunk/django/core/management/validation.py
===================================================================
--- django/trunk/django/core/management/validation.py   2008-08-19 13:51:12 UTC 
(rev 8441)
+++ django/trunk/django/core/management/validation.py   2008-08-19 14:17:24 UTC 
(rev 8442)
@@ -68,7 +68,7 @@
             # fields, m2m fields, m2m related objects or related objects
             if f.rel:
                 if f.rel.to not in models.get_models():
-                    e.add(opts, "'%s' has relation with model %s, which has 
not been installed" % (f.name, f.rel.to))
+                    e.add(opts, "'%s' has a relation with model %s, which has 
either not been installed or is abstract." % (f.name, f.rel.to))
                 # it is a string and we could not find the model it refers to
                 # so skip the next section
                 if isinstance(f.rel.to, (str, unicode)):
@@ -105,7 +105,7 @@
             # existing fields, m2m fields, m2m related objects or related
             # objects
             if f.rel.to not in models.get_models():
-                e.add(opts, "'%s' has m2m relation with model %s, which has 
not been installed" % (f.name, f.rel.to))
+                e.add(opts, "'%s' has an m2m relation with model %s, which has 
either not been installed or is abstract." % (f.name, f.rel.to))
                 # it is a string and we could not find the model it refers to
                 # so skip the next section
                 if isinstance(f.rel.to, (str, unicode)):

Modified: django/trunk/django/db/models/fields/related.py
===================================================================
--- django/trunk/django/db/models/fields/related.py     2008-08-19 13:51:12 UTC 
(rev 8441)
+++ django/trunk/django/db/models/fields/related.py     2008-08-19 14:17:24 UTC 
(rev 8442)
@@ -646,6 +646,7 @@
         except AttributeError: # to._meta doesn't exist, so it must be 
RECURSIVE_RELATIONSHIP_CONSTANT
             assert isinstance(to, basestring), "%s(%r) is invalid. First 
parameter to ForeignKey must be either a model, a model name, or the string %r" 
% (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
         else:
+            assert not to._meta.abstract, "%s cannot define a relation with 
abstract class %s" % (self.__class__.__name__, to._meta.object_name)
             to_field = to_field or to._meta.pk.name
         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
 
@@ -756,6 +757,11 @@
 
 class ManyToManyField(RelatedField, Field):
     def __init__(self, to, **kwargs):
+        try:
+            assert not to._meta.abstract, "%s cannot define a relation with 
abstract class %s" % (self.__class__.__name__, to._meta.object_name)
+        except AttributeError: # to._meta doesn't exist, so it must be 
RECURSIVE_RELATIONSHIP_CONSTANT
+            assert isinstance(to, basestring), "%s(%r) is invalid. First 
parameter to ManyToManyField must be either a model, a model name, or the 
string %r" % (self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT)
+
         kwargs['verbose_name'] = kwargs.get('verbose_name', None)
         kwargs['rel'] = ManyToManyRel(to,
             num_in_admin=kwargs.pop('num_in_admin', 0),

Modified: django/trunk/tests/modeltests/invalid_models/models.py
===================================================================
--- django/trunk/tests/modeltests/invalid_models/models.py      2008-08-19 
13:51:12 UTC (rev 8441)
+++ django/trunk/tests/modeltests/invalid_models/models.py      2008-08-19 
14:17:24 UTC (rev 8442)
@@ -5,7 +5,7 @@
 """
 
 from django.db import models
-model_errors = ""
+
 class FieldErrors(models.Model):
     charfield = models.CharField()
     decimalfield = models.DecimalField()
@@ -168,6 +168,15 @@
     third = models.ForeignKey(Group, related_name="rel_to_set")
     date_added = models.DateTimeField()
 
+class AbstractModel(models.Model):
+    name = models.CharField(max_length=10)
+    class Meta:
+        abstract = True
+
+class AbstractRelationModel(models.Model):
+    fk1 = models.ForeignKey('AbstractModel')
+    fk2 = models.ManyToManyField('AbstractModel')
+    
 model_errors = """invalid_models.fielderrors: "charfield": CharFields require 
a "max_length" attribute.
 invalid_models.fielderrors: "decimalfield": DecimalFields require a 
"decimal_places" attribute.
 invalid_models.fielderrors: "decimalfield": DecimalFields require a 
"max_digits" attribute.
@@ -250,8 +259,8 @@
 invalid_models.selfclashm2m: Accessor for m2m field 'm2m_4' clashes with 
related m2m field 'SelfClashM2M.selfclashm2m_set'. Add a related_name argument 
to the definition for 'm2m_4'.
 invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_3' clashes 
with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the 
definition for 'm2m_3'.
 invalid_models.selfclashm2m: Reverse query name for m2m field 'm2m_4' clashes 
with field 'SelfClashM2M.selfclashm2m'. Add a related_name argument to the 
definition for 'm2m_4'.
-invalid_models.missingrelations: 'rel2' has m2m relation with model Rel2, 
which has not been installed
-invalid_models.missingrelations: 'rel1' has relation with model Rel1, which 
has not been installed
+invalid_models.missingrelations: 'rel1' has a relation with model Rel1, which 
has either not been installed or is abstract.
+invalid_models.missingrelations: 'rel2' has an m2m relation with model Rel2, 
which has either not been installed or is abstract.
 invalid_models.grouptwo: 'primary' has a manually-defined m2m relation through 
model Membership, which does not have foreign keys to Person and GroupTwo
 invalid_models.grouptwo: 'secondary' has a manually-defined m2m relation 
through model MembershipMissingFK, which does not have foreign keys to Group 
and GroupTwo
 invalid_models.missingmanualm2mmodel: 'missing_m2m' specifies an m2m relation 
through model MissingM2MModel, which has not been installed
@@ -260,4 +269,6 @@
 invalid_models.personselfrefm2m: Many-to-many fields with intermediate tables 
cannot be symmetrical.
 invalid_models.personselfrefm2m: Intermediary model RelationshipTripleFK has 
more than two foreign keys to PersonSelfRefM2M, which is ambiguous and is not 
permitted.
 invalid_models.personselfrefm2mexplicit: Many-to-many fields with intermediate 
tables cannot be symmetrical.
+invalid_models.abstractrelationmodel: 'fk1' has a relation with model 
AbstractModel, which has either not been installed or is abstract.
+invalid_models.abstractrelationmodel: 'fk2' has an m2m relation with model 
AbstractModel, which has either not been installed or is abstract.
 """


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to