Reputation: 736
I'm trying to filter out the results from a model so all fields return, but I can filter just one ManyToManyField in the model. I'd only like it to filter out on the page, and not in the Admin.
I've found some great information about ManyToMany filtering but, for some reason, nothing that helps in this particular case. So I guess I'm either doing it very wrong, or I'm missing an important search term. I've tried filtering in models, in views, and in the template.
Here's a minimal example to help explain:
# models.py
class Foo(models.Model):
name = models.CharField(unique=True, max_length=255)
bars = models.ManyToManyField(Bar)
class Bar(models.Model):
thing = models.CharField(max_length=12)
is_public = models.BooleanField(default=False)
# views.py
class FooDetail(DetailView):
def get_queryset(self):
# Would I filter in here?
return super(FooDetail, self).get_queryset()
I would like the Foo model to return all foos
, but for each foo only includes bars
that are true for is_public
Where do I filter out the Bar results for the Foo model?
I found this question which is basically what I'm asking, but the answer is specific to that question and shows it filtered in the Serializer. So I don't understand how/where to apply that answer here where I'm not doing any serialization. (should I be?)
Upvotes: 1
Views: 29
Reputation: 21802
You can use Prefetch()
objects [Django docs] and pass the queryset
keyword argument to do this:
from django.db.models import Prefetch
foo_queryset = Foo.objects.prefetch_related(
Prefetch(
'bar_set',
queryset=Bar.objects.filter(is_public=True),
to_attr='public_bars'
)
)
Now you can access the related Bar
instances which are public by using:
for foo in foo_queryset:
print(foo.public_bars)
Upvotes: 1