Wedava
Wedava

Reputation: 1231

Django: Using prefetch_selected with get() and filter()

I am trying to make queries using prefetch_selected to prefetch many to many objects. Using prefetch_selected when doing an all() query works okay but I do not know how i’m supposed to use it with get() or filter(). Here is my model:

class Project(models.Model):
    …
    funders = models.ManyToManyField(Organization, related_name="funders")

class Organization(models.Model):
    …
    name = models.CharField(max_length=200, unique=True)

Trying the lines below doesn’t seem to work:

Project.objects.get(id=project_id).select_related('funders')

and

Project.objects.filter(id__in=[‘list-of-ids]).select_related('funders')

How i’m I supposed to go about it?

Thanks in advance.

Upvotes: 1

Views: 280

Answers (3)

knbk
knbk

Reputation: 53699

select_related() is a queryset method. The documentation on querysets has two sections of methods: methods that return a new queryset, and methods that do not return a queryset. get() is in the second section, so you can't chain any other queryset methods after it.

One other thing: prefetch_related() runs an extra query for each model. Since you're only fetching a single project, project.funders.all() will run exactly 1 query to fetch all related organizations regardless of your use of prefetch_related(). prefetch_related becomes useful when you need the related organizations for multiple projects.

Upvotes: 1

Du D.
Du D.

Reputation: 5310

Since funder is m2m you cannot use select_related, you have to us prefetch instead. select_related only work on foreign key and one to one relation

Project.objects.prefetch_related('funders').filter(id__in=[id1, id2])

Upvotes: 0

Leistungsabfall
Leistungsabfall

Reputation: 6488

You chained them in the wrong order, do it this way:

Project.objects.select_related('funders').get(id=project_id)

and

Project.objects.select_related('funders').filter(id__in=[‘list-of-ids])

You have to call select_related and prefetch_related on the Manager object (Project.objects).

Upvotes: 1

Related Questions