When to Use Get, Get_Queryset, Get_Context_Data in Django

When to use get, get_queryset, get_context_data in Django?

They indeed do different things.

get()

This is a top-level method, and there's one for each HTTP verb - get(), post(), patch(), etc. You would override it when you want to do something before a request is processed by the view, or after. But this is only called when a form view is loaded for the first time, not when the form is submitted. Basic example in the documentation. By default it will just render the configured template and return the HTML.

class MyView(TemplateView):
# ... other methods

def get(self, *args, **kwargs):
print('Processing GET request')
resp = super().get(*args, **kwargs)
print('Finished processing GET request')
return resp

get_queryset()

Used by ListViews - it determines the list of objects that you want to display. By default, it will just give you all for the model you specify. By overriding this method you can extend or completely replace this logic. Django documentation on the subject.

class FilteredAuthorView(ListView):
template_name = 'authors.html'
model = Author

def get_queryset(self):
# original qs
qs = super().get_queryset()
# filter by a variable captured from url, for example
return qs.filter(name__startswith=self.kwargs['name'])

get_context_data()

This method is used to populate a dictionary to use as the template context. For example, ListViews will populate the result from get_queryset() as author_list in the above example. You will probably be overriding this method most often to add things to display in your templates.

def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['page_title'] = 'Authors'
return data

And then in your template, you can reference these variables.

<h1>{{ page_title }}</h1>

<ul>
{% for author in author_list %}
<li>{{ author.name }}</li>
{% endfor %}
</ul>

Now to answer your main question, the reason you have so many methods is to let you easily stick your custom logic with pin-point accuracy. It not only allows your code to be more readable and modular, but also more testable.

The documentation should explain everything. If still not enough, you may find the sources helpful as well. You'll see how everything is implemented with mixins which are only possible because everything is compartmentalized.

How to pass value from get_queryset() to get_context_data()

When a list view is paginated, you can access the paginator in the template context with paginator.

Therefore you can access the length of the entire (unpaginated) queryset with:

{{ paginator.count }}

As an aside, your get_queryset method should always return a list or a queryset. When search_text is not specified, you could return an empty queryset, Store.objects.none().

def get_queryset(self):
...

if search_text:
...
else:
search_stores = Store.objects.none()

return search_stores

I would also avoid looping over the queryset to set store.mKey = store.mKey.split(' '). This will evaluate the entire queryset, not just the page that you are displaying. It might be better to add a property to your model, for example:

class Store(models.Model):
...

@property
def mkey_list(self):
return self.mKey.split(' ')

Then in your template you can do something like:

{% for key in store.mkey_list %}
{{ key }}
{% endfor %}

Django: get_queryset after get_context_data

Just filter inside of get_queryset method

def get_queryset(self, *args, **kwargs):
queryset = super().get_queryset(*args, **kwargs)
search = self.request.GET.get('buscar', None)
queryset = queryset.filter(engineer=self.request.user)
if search:
queryset = queryset.filter(
Q(project_title__icontains=search) |
Q(category__title__icontains=search)
).distinct()
return queryset

get context data in get_queryset

for Listview get_quersyset() is called before get_contex_data() , hence getting context data is not possible in get_queryset()

How to define get_queryset, get_context_data in a django view?

First of all you need to establish a ForeignKey relationship between your models.

#models.py
from django.db import models

class Book(models.Model):
title = models.CharField(max_length = 250)
author = models.ForeignKey(Author, related_name="books")

def __unicode__(self):
return self.Title

Now in your view you should be able to retrieve your list of authors by overriding the get_queryset method like this:

#views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import TemplateView, ListView

from .models import Author

class BooksByAuthorList(ListView):
model = Book
template_name = 'instancias/pruebas.html'

def get_queryset(self):
return Author.objects.prefetch_related("books").all()

With just the above view you should be able to have in your template:

<ul>
{% for author in object_list %}
<li>{{author.name}}</li><ul>
{% for book in author.books.all %}
<li>book.title</li>
{% endfor %}
</ul>
{% endfor %}
</ul>

Now say you want to customize that so that instead of the generic object_list the context variable was instead something sensible in the domain like authors.

Just augment your view like this:

class BooksByAuthorList(ListView):
model = Author
template_name = 'instancias/pruebas.html'
context_object_name = 'authors'

def get_queryset(self):
return Author.objects.prefetch_related("books").all()

Note you don't need get_context_data at all yet.

Assuming you'd like to include some additional data you'll just want to override get_context_data and in this case you'll want to keep the object list that's already in your context by calling the superclasses get_context_data method first.

Just do:

    def get_context_data(self, *args, **kwargs):
# Call the base implementation first to get a context
context = super(BooksByAuthorList, self).get_context_data(*args, **kwargs)
# add whatever to your context:
context['whatever'] = "MORE STUFF"
return context

get_context_data arguments are determined by your routes. *args and **kwargs should probably be replaced with something specific to your view and route in your actual code.



Related Topics



Leave a reply



Submit