2

Good day for all!

My app used django class-based generic list view. I have two model objects: Books and Publishers that linked via foreign key (code below). I want to use ListView to show publishers with their books, but filter books (get only active books, owned by current user)

Additional info: I don't want to use filter in template if it's possible. Additional info 2: I can't use filter via define in model class because I need access to request object

code

models.py

class Publisher(models.Model):
    name = models.CharField(max_length=255)

class Book(models.Model):
    name = models.CharField(max_length=255)
    active = models.BooleanField(default=True)
    publisher = models.ForeignKey(Publisher, related_name='books')
    owner = models.ForeignKey(User)

views.py

class ListBooksByPublisher(ListView):
    model = Publisher
    template_name = 'list.html'
    context_object_name = 'books'

list.html

{% for publisher in publishers %}
    {{ publisher.name }}
    {% for book in publisher.books.all %}
        {{ book.name }}
    {% endfor %}
{% endfor %}

Any help much appreciated!

3 Answers 3

8

you need to overwrite the get_queryset method on the view to return your custom queryset

For example:

class ListBooksByPublisher(ListView):
    ....
    def get_queryset(self):
        return self.model.objects.filter(blablabla))

Hope this helps

Sign up to request clarification or add additional context in comments.

4 Comments

I use get_queryset to filter Publisher (parent object). But I can't understand how to use it to filter child objects.
that's a different question :) create another question on SO on how to filter sub child objects
Thats is exact question I asked. Django filtering child objects
You migth want to check this code.djangoproject.com/ticket/17001 . You are looking to add filters to the related objects
0

You may write your custom filter, which returns list of books for a publisher.

yourapp/templatetags/my_filters.py:

from django import template
register = template.Library()

@register.filter
def get_books(publisher):
    return publisher.book_set.filter(YOUR_CUSTOM_FILTER)

Your template:

{% load get_books from my_filters %}
...
{% for publisher in publishers %}
    {{ publisher.name }}
    {% for book in publisher|get_books %}
        {{ book.name }}
    {% endfor %}
{% endfor %}

Another way is to pass extra data to your view:

class ListBooksByPublisher(ListView):
    ...
    def get_context_data(self, **kwargs):
        context = super(ListBooksByPublisher, self).get_context_data(**kwargs)
        context['publishers_with_books'] = your_custom_data_structure
        return context

1 Comment

Just keep one thing in mind: there is nothing wrong with using the function based view if your requirements are too complex for a CBV.
-2
#views
class ListBooksByPublisher(ListView):
    model = Publisher
    template_name = 'list.html'
    context_object_name = 'publishers'
#tmp
{% for publisher in publishers %}
    {{ publisher.name }}
    {% for book in publisher.book_set.all %}
        {{ book.name }}
    {% endfor %}
{% endfor %}

1 Comment

I can't find a filter here, sorry.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.