Reputation: 422
I have three models, let's call them models A, B and C.
A and B share one-to-one relationship, A can exists without B but B must always be linked to A. C has many-to-one relation with B. Or in other words:
class ModelA(models.Model):
#properties
class ModelB(models.Model):
a_link = models.OneToOneField(A, on_delete=models.CASCADE, related_name='a_link')
#rest of the properties
class ModelC(models.Model):
set = models.ForeignKey(ModelB, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True)
Now, my question is, I want to find all A's that user has, by checking what Cs they have been tagged in. Can I just do search ModelA.objects.filter(a_link__modelc__user=user)
or do I need to first search for Cs in their own query, then select Bs from them and look for their relationship with A?
Upvotes: 1
Views: 333
Reputation: 477308
You can filter with:
ModelA.objects.filter(a_link__modelc__user=user).distinct()
The .distinct()
is useful here to avoid that the same ModelA
is in the QuerySet
multiple times if there are multiple related ModelC
s that have as user
the user
object.
Since the related_name
is however the name of the relation in reverse, you might want to rename this to for example:
class ModelA(models.Model):
#properties
class ModelB(models.Model):
a_link = models.OneToOneField(
ModelA,
on_delete=models.CASCADE,
related_name='b_object'
)
# rest of the properties
class ModelC(models.Model):
set = models.ForeignKey(ModelB, on_delete=models.CASCADE)
user = models.ForeignKey(
User,
on_delete=models.SET_NULL,
blank=True,
null=True
)
then the query is thus:
ModelA.objects.filter(b_object__modelc__user=user).distinct()
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL
[Django-doc] to refer to the user model, than to use theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Upvotes: 1