django-dia icon indicating copy to clipboard operation
django-dia copied to clipboard

Manage ForeignKey from Abstract

Open gaionim opened this issue 7 years ago • 3 comments

Hi, I've model like this

class AbstractClass(models.Model):
    field = models.ForeignKey("related_field")

    class Meta:
        abstract = True

class RealClass(AbstractClass):

    other_field = models.CharField()`

with django 11 get_relation_target_field() in utils.py raises exception

return target_model._meta.pk
AttributeError: 'unicode' object has no attribute '_meta'

This is labelled as # 1.8 compat, so I think someting wrong in previus

# newer django
if hasattr(rel_field, 'target_field'):
    return rel_field.target_field

PS django-extensions fails too,

gaionim avatar Jun 01 '18 09:06 gaionim

Hi, this is probably a Django bug. Fails for me if I do:

class AbstractModelG(models.Model):
    field = models.ForeignKey('ReferencedModelG', on_delete=models.CASCADE)

    class Meta:
        abstract = True

class RealModelG(AbstractModelG):
    other_field = models.CharField(max_length=100)

class ReferencedModelG(models.Model):
    field = models.FloatField()

with ValueError: Related model 'ReferencedModelG' cannot be resolved on Django 2.0.6. But if I remove abstract model, everything works fine:

class RealModelG(models.Model):
    field = models.ForeignKey('ReferencedModelG', on_delete=models.CASCADE)
    other_field = models.CharField(max_length=100)

class ReferencedModelG(models.Model):
    field = models.FloatField()

Your error reproduces here under py2+django1.11: https://travis-ci.org/neumond/django-dia/builds/387263880

It tries to read target_field property of ForeignKey field and fails here. If you try to print model right before this:

def get_relation_target_field(rel_field):
    print(rel_field.related_model)
    ...

you'll see that everything here is a model class, except the failing case, which is still an unresolved string.

Another workaround is avoiding textual names:

class ReferencedModelG(models.Model):
    field = models.FloatField()

class AbstractModelG(models.Model):
    # magically works
    field = models.ForeignKey(ReferencedModelG, on_delete=models.CASCADE)

    class Meta:
        abstract = True

neumond avatar Jun 03 '18 00:06 neumond

Reported this to django: https://code.djangoproject.com/ticket/29466

neumond avatar Jun 03 '18 02:06 neumond

thanks

gaionim avatar Jun 03 '18 05:06 gaionim