Commit 63f0e2df authored by Simon Charette's avatar Simon Charette
Browse files

Refs #18012 -- Accounted for reverse proxy relations in migrations.

Thanks to Markus for the suggestion and Tim for the review.
parent 3db3ab71
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -41,13 +41,21 @@ def get_related_models_recursive(model):
    its superclass through the implicit *_ptr OneToOneField on the subclass.
    """
    def _related_models(m):
        return [
            f.related_model for f in m._meta.get_fields(include_parents=True, include_hidden=True)
            if f.is_relation and f.related_model is not None and not isinstance(f.related_model, six.string_types)
        ] + [
        related_models = [
            subclass for subclass in m.__subclasses__()
            if issubclass(subclass, models.Model)
        ]
        related_fields_models = set()
        for f in m._meta.get_fields(include_parents=True, include_hidden=True):
            if f.is_relation and f.related_model is not None and not isinstance(f.related_model, six.string_types):
                related_fields_models.add(f.model)
                related_models.append(f.related_model)
        # Reverse accessors of foreign keys to proxy models
        # are attached to their concrete proxied model.
        opts = m._meta
        if opts.proxy and m in related_fields_models:
            related_models.append(opts.concrete_model)
        return related_models

    seen = set()
    queue = _related_models(model)
+10 −0
Original line number Diff line number Diff line
@@ -960,6 +960,16 @@ class RelatedModelsTests(SimpleTestCase):
        self.assertRelated(A, [B])
        self.assertRelated(B, [A])

    def test_fk_through_proxy(self):
        A = self.create_model("A")
        B = self.create_model("B", bases=(A,), proxy=True)
        C = self.create_model("C", bases=(B,), proxy=True)
        D = self.create_model("D", foreign_keys=[models.ForeignKey('C', models.CASCADE)])
        self.assertRelated(A, [B, C, D])
        self.assertRelated(B, [A, C, D])
        self.assertRelated(C, [A, B, D])
        self.assertRelated(D, [A, B, C])

    def test_nested_fk(self):
        A = self.create_model("A", foreign_keys=[models.ForeignKey('B', models.CASCADE)])
        B = self.create_model("B", foreign_keys=[models.ForeignKey('C', models.CASCADE)])