Ticket #11226: 11226-r12343.diff

File 11226-r12343.diff, 7.0 KB (added by ramiro, 5 years ago)

Patch updated to current trunk. Includes tests, fixes a related validation that was wrongly being triggered and a couple of docstrings typo fixes.

  • django/core/management/validation.py

    diff --git a/django/core/management/validation.py b/django/core/management/validation.py
    a b  
    175175                    )
    176176                else:
    177177                    seen_intermediary_signatures.append(signature)
    178                 seen_related_fk, seen_this_fk = False, False
    179                 for field in f.rel.through._meta.fields:
    180                     if field.rel:
    181                         if not seen_related_fk and field.rel.to == f.rel.to:
    182                             seen_related_fk = True
    183                         elif field.rel.to == cls:
    184                             seen_this_fk = True
    185                 if not seen_related_fk or not seen_this_fk:
    186                     e.add(opts, "'%s' has a manually-defined m2m relation "
    187                         "through model %s, which does not have foreign keys "
    188                         "to %s and %s" % (f.name, f.rel.through._meta.object_name,
    189                             f.rel.to._meta.object_name, cls._meta.object_name)
    190                     )
     178                if not f.rel.through._meta.auto_created:
     179                    seen_related_fk, seen_this_fk = False, False
     180                    for field in f.rel.through._meta.fields:
     181                        if field.rel:
     182                            if not seen_related_fk and field.rel.to == f.rel.to:
     183                                seen_related_fk = True
     184                            elif field.rel.to == cls:
     185                                seen_this_fk = True
     186                    if not seen_related_fk or not seen_this_fk:
     187                        e.add(opts, "'%s' is a manually-defined m2m relation "
     188                            "through model %s, which does not have foreign keys "
     189                            "to %s and %s" % (f.name, f.rel.through._meta.object_name,
     190                                f.rel.to._meta.object_name, cls._meta.object_name)
     191                        )
    191192            elif isinstance(f.rel.through, basestring):
    192193                e.add(opts, "'%s' specifies an m2m relation through model %s, "
    193194                    "which has not been installed" % (f.name, f.rel.through)
  • tests/modeltests/invalid_models/models.py

    diff --git a/tests/modeltests/invalid_models/models.py b/tests/modeltests/invalid_models/models.py
    a b  
    268268invalid_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'.
    269269invalid_models.missingrelations: 'rel1' has a relation with model Rel1, which has either not been installed or is abstract.
    270270invalid_models.missingrelations: 'rel2' has an m2m relation with model Rel2, which has either not been installed or is abstract.
    271 invalid_models.grouptwo: 'primary' has a manually-defined m2m relation through model Membership, which does not have foreign keys to Person and GroupTwo
    272 invalid_models.grouptwo: 'secondary' has a manually-defined m2m relation through model MembershipMissingFK, which does not have foreign keys to Group and GroupTwo
     271invalid_models.grouptwo: 'primary' is a manually-defined m2m relation through model Membership, which does not have foreign keys to Person and GroupTwo
     272invalid_models.grouptwo: 'secondary' is a manually-defined m2m relation through model MembershipMissingFK, which does not have foreign keys to Group and GroupTwo
    273273invalid_models.missingmanualm2mmodel: 'missing_m2m' specifies an m2m relation through model MissingM2MModel, which has not been installed
    274274invalid_models.group: The model Group has two manually-defined m2m relations through the model Membership, which is not permitted. Please consider using an extra field on your intermediary model instead.
    275275invalid_models.group: Intermediary model RelationshipDoubleFK has more than one foreign key to Person, which is ambiguous and is not permitted.
  • tests/regressiontests/m2m_regress/models.py

    diff --git a/tests/regressiontests/m2m_regress/models.py b/tests/regressiontests/m2m_regress/models.py
    a b  
    11from django.db import models
     2from django.contrib import auth
    23
    34# No related name is needed here, since symmetrical relations are not
    45# explicitly reversible.
     
    4142    id = models.CharField(primary_key=True, max_length=100)
    4243    lines = models.ManyToManyField(Line, blank=True, null=True)
    4344
     45# A model with the same name that another one to which it has a m2m relation,
     46# This shouldn't cause a name clash between the automatically created m2m
     47# intermediary table FK field names when running syncdb (#11226)
     48class User(models.Model):
     49    name = models.CharField(max_length=30)
     50    friends = models.ManyToManyField(auth.models.User)
     51
    4452__test__ = {"regressions": """
    4553# Multiple m2m references to the same model or a different model must be
    4654# distinguished when accessing the relations through an instance attribute.
  • django/db/models/fields/related.py

    diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
    a b  
    511511        def _add_items(self, source_field_name, target_field_name, *objs):
    512512            # join_table: name of the m2m link table
    513513            # source_field_name: the PK fieldname in join_table for the source object
    514             # target_col_name: the PK fieldname in join_table for the target object
     514            # target_field_name: the PK fieldname in join_table for the target object
    515515            # *objs - objects to add. Either object instances, or primary keys of object instances.
    516516
    517517            # If there aren't any objects, there is nothing to do.
     
    914914        to_model = field.rel.to
    915915        managed = klass._meta.managed or to_model._meta.managed
    916916    name = '%s_%s' % (klass._meta.object_name, field.name)
    917     if field.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or field.rel.to == klass._meta.object_name:
     917    if field.rel.to == RECURSIVE_RELATIONSHIP_CONSTANT or to == klass._meta.object_name:
    918918        from_ = 'from_%s' % to.lower()
    919919        to = 'to_%s' % to.lower()
    920920    else:
     
    973973                                      connection.ops.max_name_length())
    974974
    975975    def _get_m2m_attr(self, related, attr):
    976         "Function that can be curried to provide the source column name for the m2m table"
     976        "Function that can be curried to provide the source accessor or DB column name for the m2m table"
    977977        cache_attr = '_m2m_%s_cache' % attr
    978978        if hasattr(self, cache_attr):
    979979            return getattr(self, cache_attr)
     
    983983                return getattr(self, cache_attr)
    984984
    985985    def _get_m2m_reverse_attr(self, related, attr):
    986         "Function that can be curried to provide the related column name for the m2m table"
     986        "Function that can be curried to provide the related accessor or DB column name for the m2m table"
    987987        cache_attr = '_m2m_reverse_%s_cache' % attr
    988988        if hasattr(self, cache_attr):
    989989            return getattr(self, cache_attr)
Back to Top