Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define get_queryset, get_context_data in a django view?

I want show a tree with Authors and Books written for each Author in sub item, like show in the image and... I have two models Author and Book in a OneToMany relationship.

#models.py
from django.db import models

class Author(models.Model):
    Name = models.CharField(max_length = 250)

    def __unicode__(self):
        return self.Name

class Book(models.Model):
    Title = models.CharField(max_length = 250)

    def __unicode__(self):
        return self.Title


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

from .models import InstanciaJudicial, SedeJudicial

class Prueba(ListView):
    model = SedeJudicial
    template_name = 'instancias/pruebas.html'

I know that I defined get_queryset and get_context_data, but I don't know how I did this.

like image 424
Elio Clímaco Herrera Avatar asked Jan 31 '26 08:01

Elio Clímaco Herrera


1 Answers

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.

like image 136
stderr Avatar answered Feb 01 '26 21:02

stderr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!