django-typed-models
django-typed-models copied to clipboard
Demonstrate bug where related_name is not working properly when using…
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/apps/registry.py", line 433, in do_pending_operations
function(model)
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/apps/registry.py", line 411, in apply_next_model
self.lazy_model_operation(next_function, *more_models)
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/apps/registry.py", line 397, in lazy_model_operation
function()
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/db/models/fields/related.py", line 373, in resolve_related_class
field.do_related_class(related, model)
File "/Users/mcosti/dev/django-typed-models/typedmodels/models.py", line 108, in do_related_class
old_do_related_class(other, cls)
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/db/models/fields/related.py", line 448, in do_related_class
self.set_attributes_from_rel()
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/db/models/fields/related.py", line 445, in set_attributes_from_rel
self.remote_field.set_field_name()
File "/Users/mcosti/dev/django-typed-models/env/bin/activate/lib/python3.9/site-packages/django/db/models/fields/reverse_related.py", line 306, in set_field_name
self.field_name = self.field_name or self.model._meta.pk.name
AttributeError: 'str' object has no attribute '_meta'
The culprit lives somewhere here
if isinstance(field, models.fields.related.RelatedField):
# Monkey patching field instance to make do_related_class use created class instead of base_class.
# Actually that class doesn't exist yet, so we just monkey patch base_class for a while,
# changing _meta.model_name, so accessor names are generated properly.
# We'll do more stuff when the class is created.
old_do_related_class = field.do_related_class
def do_related_class(self, other, cls):
base_class_name = base_class.__name__
cls._meta.model_name = classname.lower()
old_do_related_class(other, cls)
cls._meta.model_name = base_class_name.lower()
field.do_related_class = types.MethodType(do_related_class, field)
if isinstance(field, models.fields.related.RelatedField):
remote_field = field.remote_field
if (
isinstance(remote_field.model, TypedModel)
and remote_field.model.base_class
):
remote_field.limit_choices_to[
"type__in"
] = remote_field.model._typedmodels_subtypes
This is fixed now. I added a print in RelatedFIeld.resolve_related_class
Without my changes:
<class 'testapp.models.UniqueIdentifier'> <class 'django.contrib.contenttypes.models.ContentType'> testapp.UniqueIdentifier.content_type
<class 'testapp.models.Animal'> <class 'testapp.models.UniqueIdentifier'> testapp.Animal.unique_identifiers
<class 'testapp.models.Canine'> <class 'testapp.models.UniqueIdentifier'> testapp.Canine.unique_identifiers
<class 'testapp.models.Feline'> <class 'testapp.models.UniqueIdentifier'> testapp.Feline.unique_identifiers
<class 'testapp.models.BigCat'> <class 'testapp.models.UniqueIdentifier'> testapp.BigCat.unique_identifiers
<class 'testapp.models.Animal'> <class 'testapp.models.Canine'> testapp.Animal.canines_eaten
<class 'testapp.models.Animal_canines_eaten'> <class 'testapp.models.Animal'> testapp.Animal_canines_eaten.animal
<class 'testapp.models.Animal_canines_eaten'> <class 'testapp.models.Canine'> testapp.Animal_canines_eaten.canine
<class 'testapp.models.AngryBigCat'> <class 'testapp.models.UniqueIdentifier'> testapp.AngryBigCat.unique_identifiers
<class 'testapp.models.Parrot'> <class 'testapp.models.UniqueIdentifier'> testapp.Parrot.unique_identifiers
<class 'testapp.models.Parent'> <class 'testapp.models.Parent'> testapp.Parent.b
<class 'second_testapp.models.BaseReview'> <class 'testapp.models.Product'> second_testapp.BaseReview.product
With the changes (respecting the same way Django deals with these things):
<class '__fake__.Animal_canines_eaten'> <class '__fake__.Animal'> testapp.Animal_canines_eaten.animal
<class '__fake__.Animal_canines_eaten'> <class '__fake__.Canine'> testapp.Animal_canines_eaten.canine
<class '__fake__.Animal'> <class '__fake__.Canine'> testapp.Animal.canines_eaten
<class '__fake__.Parent'> <class '__fake__.Parent'> testapp.Parent.b
<class '__fake__.BaseReview'> <class '__fake__.Product'> second_testapp.BaseReview.product
<class '__fake__.BaseReview'> <class '__fake__.Order'> second_testapp.BaseReview.order
<class '__fake__.Order'> <class '__fake__.Product'> testapp.Order.product
@craigds if you could please have a look that would be amazing. Thank you
Hey @craigds . Any updates? This no longer impacts me as I've removed the depdency, but I think it's still a good QoL improvement