Reputation: 53
I'm trying to create a twitter like application as a practice project, and following this video tutorial. I've created following models in my app.
class Profile(models.Model):
user = models.OneToOneField(to=User, on_delete=models.CASCADE)
bio = models.CharField(max_length=160, blank=True)
profile_photo = models.ImageField(blank=True, null=True)
followers = models.ManyToManyField("self", through="Relationship", related_name="follow_to",
symmetrical=False, blank=True)
class Relationship(models.Model):
user_followed = models.ForeignKey("User", related_name="followed", on_delete=models.CASCADE)
followed_by = models.ForeignKey("Profile", related_name="follower", on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now=True)
The migrations ran successfully.
After this for testing, I created two users (user1 and user2) with their respective profiles and made user2 to follow user1. Here's the code for that-
Relationship.objects.create(user_followed=user1,followed_by=user2.profile)
This relationship was successfully created. I try the following code to try to get followers of user1-
user1.profile.followers.all()
But above code is giving following errors-
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 535, in __get__
return self.related_manager_cls(instance)
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 821, in __init__
self.target_field_name = rel.field.m2m_reverse_field_name()
File "/Users/mayank/.pyenv/versions/dwitter/lib/python3.8/site-packages/django/db/models/fields/related.py", line 1554, in _get_m2m_reverse_attr
return getattr(self, cache_attr)
AttributeError: 'ManyToManyField' object has no attribute '_m2m_reverse_name_cache'
I tried following the method mentioned here, but it is also giving the same error. I'm not sure where have I committed a mistake. I would be thankful if someone can correct me.
Upvotes: 1
Views: 404
Reputation: 476534
Since you make an ManyToManyField
to 'self'
both the ForeignKey
s should point to Profile
:
class Relationship(models.Model):
followed = models.ForeignKey(
'Profile',
related_name='followed',
on_delete=models.CASCADE
)
followed_by = models.ForeignKey(
'Profile',
related_name='follower',
on_delete=models.CASCADE
)
timestamp = models.DateTimeField(auto_now=True)
Since now both ForeignKey
s point to the same model, there is an ambiguity what the source field, and what the target field is. You resolve this by specifying this with the through_fields=…
parameter [Django-doc]:
class Profile(models.Model):
user = models.OneToOneField(to=User, on_delete=models.CASCADE)
bio = models.CharField(max_length=160, blank=True)
profile_photo = models.ImageField(blank=True, null=True)
followers = models.ManyToManyField(
'self',
through='Relationship',
related_name='follow_to',
related_fields=('followed', 'followed_by')
symmetrical=False,
blank=True
)
You thus can create a follower Relation
with:
Relationship.objects.create(
followed=user1.profile,
followed_by=user2.profile
)
Upvotes: 1