2

Can someone please explain why this doesn't work

    class MansionDesign(Listview):
        sequence = Design.objects.filter(design_type__name='maisonette').order_by('created_at').reverse()
        queryset = [sequence[i:i + 3] for i in range(0, len(sequence), 3)]
        template_name = 'designs/mansions.html'

but when i change the above class to a subclass of view like below,

    class MansionDesign(View):
        def get(self, request):
            sequence = Design.objects.filter(design_type__name='maisonette').order_by('created_at').reverse()
            queryset = [sequence[i:i + 3] for i in range(0, len(sequence), 3)]
            return render(request, 'designs/mansions.html', {'object_list': queryset})

the code seems to work just fine. The error I get from the above class is 'name sequence is not defined'. I would appreciate some clarification on this. Thanks in advance.

3
  • Please add the full traceback to questions seeking debugging help. minimal reproducible example Commented Jun 28, 2017 at 11:28
  • The actual reason for this error is explained in the duplicate question. It's not anything specific to django, but a consequence of how scoping in class definitions work in python 3. Commented Jun 28, 2017 at 11:57
  • This makes much more sense. After checking the error logs again i realized that 'sequence' was undefined in the scope of the function implementing the list comprehension. It doesn't receive the instance of the class in which the comprehension is created and thus cannot access its properties in this case 'sequence'. Commented Jun 28, 2017 at 13:09

1 Answer 1

2

Quotes from the docs:

ListView takes two params, one as queryset and second and template name.

Now if you try to define something else in the subclass of ListView you will get the error. If you do something like below:

queryset =[list(Design.objects.filter(design_type__name='maisonette').order_by('created_at').reverse())[i:i + 3] for i in range(0, len(list(Design.objects.filter(design_type__name='maisonette').order_by('created_at').reverse())), 3)]

in short - i removed the temperory variable you used as sequence. The above one will definitely won't work because its a list. The example was just to convey the point

Now the above one does not seem to be neat so if you have complex queries that you want to execute and show using listview then follow the examples below. You have to define a get_queryset method which will return the desired queryset object

class PublisherBookList(ListView):

    template_name = 'books/books_by_publisher.html'

    def get_queryset(self):
        self.publisher = get_object_or_404(Publisher, name=self.args[0])
        return Book.objects.filter(publisher=self.publisher)

Links:

https://docs.djangoproject.com/en/1.11/topics/class-based-views/generic-display/#generic-views-of-objects

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

1 Comment

Thanks this seems to make sense. I appreciate the timely response.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.