Olivier Pons Olivier Pons - 17 days ago 6
Python Question

Django Manytomany filter with intermediate model

I have the following models:

class Personne(BaseModel):
user = models.OneToOneField(User)
relations = models.ManyToManyField('self', through='PersonneRelation',
symmetrical=False,
related_name='personne_relations')

class PersonneRelation(BaseModel):
type_relation = models.IntegerField(
choices=[(a, b) for a, b in list(PersonneEnums.TAB_RELATIONS.items())],
default=PersonneEnums.RELATION_FRIEND)
src = models.ForeignKey('Personne', related_name='relation_src')
dst = models.ForeignKey('Personne', related_name='relation_dst')


In my view, I have the currently logged user via

p_user = Personne.objects.get(user=view.request.user)


I want to retrieve all the relation of
p_user
that are of type
PersonneEnums.RELATION_FRIEND


I've tried many things including the following code, but nothing works:

Doesn't work :

p_user.objects.filter(relations__type_relation__exact=PersonneEnums.RELATION_AMI)


Doesn't work:

Personne.objects.filter(
pk=p_user.pk,
relations__type_relation__exact=PersonneEnums.RELATION_AMI
)


Can someone explain to me why this does not work?

Answer

In both cases you're trying to use the default manager objects, while you need to use a relationship manager. However it seems, that there will be a problem as relationship is ambiguous, i.e. when querying relationship like this:

p_user.relations.filter(type_relation=PersonneEnums.RELATION_AMI)

Django couldn't decide if it should use src or dst in this query.

The following query should work:

PersonneRelations.objects.filter(
    Q(type_relation=PersonneEnums.RELATION_AMI), Q(src=p_user) | Q(dst=p_user))

also, something like this might work (see explanation on filter):

p_user.relations.filter(relation_src__type_relation=PersonneEnums.RELATION_AMI
               ).filter(relation_dst__type_relation=PersonneEnums.RELATION_AMI)