Django List and Details views


Example

Template views are fine for static page and you could use them for everything with get_context_data but it would be barely better than using function as views.

Enter ListView and DetailView

app/models.py

from django.db import models

class Pokemon(models.Model):
    name = models.CharField(max_length=24)
    species = models.CharField(max_length=48)
    slug = models.CharField(max_length=48)

app/views.py

from django.views.generic import ListView, DetailView
from .models import Pokemon


class PokedexView(ListView):
    """ Provide a list of Pokemon objects """
    model = Pokemon
    paginate_by = 25

class PokemonView(DetailView):
    model = Pokemon

That's all you need to generate a view listing all your objects of a models and views of singular item. The list is even paginated. You can provide template_name if you want something specific. By default, it's generated from the model name.

app/templates/app/pokemon_list.html

<!DOCTYPE html>
<title>Pokedex</title>
<ul>{% for pokemon in pokemon_list %}
    <li><a href="{% url "app:pokemon" pokemon.pk %}">{{ pokemon.name }}</a>
        &ndash; {{ pokemon.species }}
</ul>

The context is populated with the list of object under two name, object_list and a second one build from the model name, here pokemon_list. If you have paginated the list, you have to take care of next and previous link too. The Paginator object can help with that, it's available in the context data too.

app/templates/app/pokemon_detail.html

<!DOCTYPE html>
<title>Pokemon {{ pokemon.name }}</title>
<h1>{{ pokemon.name }}</h1>
<h2>{{ pokemon.species }} </h2>

As before, the context is populated with your model object under the name object and pokemon, the second one being derived from the model name.

app/urls.py

from django.conf.urls import url
from . import views

app_name = 'app'
urlpatterns = [
    url(r'^pokemon/$', views.PokedexView.as_view(), name='pokedex'),
    url(r'^pokemon/(?P<pk>\d+)/$', views.PokemonView.as_view(), name='pokemon'),
]

In this snippet, the url for the detail view is built using the primary key. It's also possible to use a slug as argument. This gives a nicer looking url that's easier to remember. However it requires the presence of a field named slug in your model.

url(r'^pokemon/(?P<slug>[A-Za-z0-9_-]+)/$', views.PokemonView.as_view(), name='pokemon'),

If a field called slug is not present, you can use the slug_field setting in DetailView to point to a different field.

For pagination, use a page get parameters or put a page directly in the url.