Hafnernuss
Hafnernuss

Reputation: 2817

Django filtering: model instance vs model pk

I stumbled upon (for me, at least) some rather odd behaviour in Django. I'm not sure if this is supported/allowed behaviour.

Suppose I have the following model:

class Club
    name = CharField(....)
    memberships = models.ManyToManyField(Person, through=ClubMembership, related_name='clubs')

    def getMembership(self, personID):
        return ClubMembership.objects.get(club_id=self.id, person_id=personID)

Obviously, getMembership returns the associated ClubMembership instance (For now, let's assume we only call this method for persons that are in fact in the club).

Now, when calling this method, I found that:

club = Club.objects.get(...)
person = Person.objects.get(...)

membership = club.getMembership(person)

and

club = Club.objects.get(...)
person = Person.objects.get(...)

membership = club.getMembership(person.id)

are both yielding the correct membership. Is there some magic happening inside the filter/get methods that check if the passend keyword (for person_id) is in fact an integer (pk) or a model instance?

If both is valid and allowed, what are the implications? Any differences performance wise? Which would be the preferred method?

Ofc I could filter against the entire person model and not just the id, like so:

def getMembership(self, person):
        return ClubMembership.objects.get(club_id=self.id, person=person)

But afaik, this would be a lot slower, right?

Upvotes: 4

Views: 736

Answers (1)

Toni Sredanović
Toni Sredanović

Reputation: 2402

As stated in Queries over related objects section of documentation there's no difference between an integer (pk) or a model instance.

In their example, if you have a Blog object b with id=5, the following three queries would be identical:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly

Upvotes: 5

Related Questions