get_queryset method in PostListView unnecessary?

I've just got to the part about class-based views.

In PostListView, rather than overriding ListView's get_queryset method, would it be better to do simply queryset = Post.objects.filter(published=True)? (And get rid of model = Post)

(This also works with PostDetailView, which I find confusing)

Perhaps you used get_queryset in order to demonstrate the mixin refactor?

Thanks

Sorry You must be a logged in, registered user to answer a question.

Answers

  1. “Sometimes you'll completely throw out the original get_queryset or get_object and write brand new ones that don't even take the CBV's model attribute into account.” Could you give a quick example?

It's obviously not a very common practice. To be honest, I usually do something like this for CreateView or UpdateView more than, say, DetailView. But, to provide an example, having a DetailView that actually needs to fetch items from Redis or MongoDB instead of the standard database would be a usecase for this. I'd argue, though, that you should really use TemplateView or something more appropriate in that case, though.

  1. “most of the time you need something that's filtered to the request”, do you mean specified in the URL path?

No, I mean the request object. Like filtering selected items down to only those owned by the user requesting the view.

  1. By “status field” do you mean a boolean thing, e.g. Post's published attribute?

Yeah, exactly. You'll see, in the next couple of lessons, a smarter way of doing this, too.

  1. By “set up a model manager for it that does that automatically and set that as the queryset” do you mean almost the same as we did in this lesson with the live method?

Similar, yes. But instead of providing a new method, like our live one, you'd just override get_query_set and have it return a pre-filtered list of items (and set this manager as the objects attribute of the model). This makes it impossible, without creating another manager or attaching models.Manager as a new attribute on the model, to select an unfiltered list of items, though.

Brilliant, thank you. I didn't quite get the final few sentences but I'll come back to that when I'm more advanced :-)
jollyfellow on

Better? Not necessarily. More explicit? Perhaps.

It obviously all comes down to the requirements of your specific project. Sometimes you won't override get_queryset or get_object and everything will work simply by specifying a model on your CBV and a slug kwarg in your URL. Sometimes you'll completely throw out the original get_queryset or get_object and write brand new ones that don't even take the CBV's model attribute into account.

A large part of me overriding get_queryset instead of just specifying a queryset attribute is that it's the more common approach when you need a custom queryset, because most of the time you need something that's filtered to the request, which can't be done through a class attribute. If you just need something to always be filtered by a status field, it's probably best to set up a model manager for it that does that automatically and set that as the queryset. But that would leave new-to-CBV developers out in the cold as to what they should do when they need more control :).

For your second question, about why queryset works on PostDetailView, all DetailView's start off fetching a queryset of items from the database which is filtered by a slug or pk argument from the URL. Then the get_object method basically does .get() on the queryset it has already fetched and that's what gives you your single object. Being able to control the queryset on a DetailView is amazingly handy.

I was thinking about your last paragraph, and I tried overriding get_object in PostDetailView -calling the superclass and returning the object -but I also included `print connection.queries`. This produced a query like: `SELECT` ... `FROM blog_post WHERE (blog_post.published = true AND blog_post.slug = my-slug)`. Does this tally with what you wrote? (I hope you don't think me pedantic at this point!)
jollyfellow on
Great, thanks. Hope you don't mind a number of possibly silly questions just so I fully understand... 1. “Sometimes you'll completely throw out the original get_queryset or get_object and write brand new ones that don't even take the CBV's model attribute into account.” Could you give a quick example? 2. “most of the time you need something that's filtered to the request”, do you mean specified in the URL path? 3. By “status field” do you mean a boolean thing, e.g. `Post`'s `published` attribute? 4. By “set up a model manager for it that does that automatically and set that as the queryset” do you mean almost the same as we did in this lesson with the `live` method? Thanks
jollyfellow on