Presen3 2
Presen3 2
Presen3 2
www.dj4e.com
Django Generic
Views
Charles Severance
www.dj4e.com
Django Generic
Views
Charles Severance
www.dj4e.com
Django Generic
Views
Browser Linux
WGSIConfig settings.py
Django
views.py
D
O
Parse
Response A diagramViews Templates
M forms.py
Database
Shell
N Models
G
I models.py
N /admin
admin.py
X
Javascript
dj4e-samples/gview/urls.py
Generic Views
from django.urls import path
from . import views
from django.views.generic import TemplateView
app_name = 'gview'
# Note use of plural for list view and singular for detail view
urlpatterns = [
path('', TemplateView.as_view(template_name='gview/main.html')),
path('cats', views.CatListView.as_view(), name='cats'),
path('cat/<int:pk_from_url>', views.CatDetailView.as_view(), name='cat'),
path('dogs', views.DogListView.as_view(), name='dogs'),
path('dog/<int:pk>', views.DogDetailView.as_view(), name='dog'),
path('horses', views.HorseListView.as_view(), name='horses'),
path('horse/<int:pk>', views.HorseDetailView.as_view(), name='horse'),
path('cars', views.CarListView.as_view(), name='cars'),
path('car/<int:pk>', views.CarDetailView.as_view(), name='car'),
path('wacky', views.WackyEquinesView.as_view(), name='whatever'),
]
Generic Views
dj4e-samples/gview/views.py
class CatListView(View):
https://samples.dj4e.com/gview/cats
dj4e-samples/gview/templates/gview/cat_list.html
<h1>Cat List</h1>
<p>
{% if cat_list %}
<ul>
{% for cat in cat_list %}
<li>
<a href="{% url 'gview:cat' cat.id %}">{{ cat.name }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no cats in the database.</p>
{% endif %}
</p>
Generic Views
dj4e-samples/gview/templates/gview/cat_detail.html
<h1>Cat {{ cat.name }}</h1>
https://samples.dj4e.com/gview/cat/1
<p>
<a href="{% url 'gview:cats' %}">Go back to list</a>
</p>
<p>
<img src="https://loremflickr.com/160/120/cat"
alt="A random picture of a cat">
</p>
dj4e-samples/gview/views.py
class CatDetailView(View):
def get(self, request, pk_from_url) :
obj = Cat.objects.get(pk=pk_from_url)
cntx = { 'cat': obj }
return render(request, 'gview/cat_detail.html', cntx)
Concept: Don't Repeat Yourself (DRY)
Don't repeat yourself (DRY, or sometimes do not repeat yourself) is a principle of
software development aimed at reducing repetition of software patterns]
replacing it with abstractions or using data normalization to avoid redundancy.
The principle has been formulated by Andy Hunt and Dave Thomas in their book
The Pragmatic Programmer.
We can recognize certain common tasks, like displaying a list of model objects, and write code
that displays a list of any model object. Django ships with generic views to display list and
detail pages for a single model object.
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
Convention over Configuration
Convention over configuration is a software design paradigm used by software
frameworks that attempts to decrease the number of decisions that a
developer using the framework is required to make without necessarily losing
flexibility.
https://en.wikipedia.org/wiki/Convention_over_configuration
Convention Over Configuration
• If
• If the app_name is gview
• And the view extends django.views.generic.list.ListView
• And the view uses the model Horse
• Then
• The will automatically render a view named gview/horse_list.html
• Passing a list of Horse objects in the variable horse_list into the template
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView
Views
dj4e-samples/gview/views.py
from django.views import generic
https://samples.dj4e.com/gview/horses
class HorseListView(generic.ListView):
model = Horse
dj4e-samples/gview/templates/gview/horse_list.html
<h1>Horse List</h1>
<p>
{% if horse_list %}
<ul>
{% for horse in horse_list %}
<li>
<a href="{% url 'gview:horse' horse.id %}">{{ horse.name }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no horses in the database.</p>
{% endif %}
</p>
Views
dj4e-samples/gview/views.py
from django.views import generic
gview.views.HorseDetailView
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
views
dj4e-samples/gview/views.py
from django.views import generic
https://samples.dj4e.com/gview/horse/1
class HorseDetailView(generic.DetailView):
model = Horse
dj4e-samples/gview/templates/gview/horse_detail.html
<h1>Horse {{ horse.name }}</h1>
<p>
<img src="https://loremflickr.com/160/120/horse"
alt="A random picture of a horse">
</p>
<p>
<a href="{% url 'gview:horses' %}">Go back to list</a>
</p>
class HorseListView(generic.ListView):
model = Horse
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
Views
dj4e-samples/gview/views.py
# Lets review how inheritance works to avoid repeating ourselves
https://samples.dj4e.com/gview/cars
https://docs.djangoproject.com/en/3.0/topics/class-based-views/generic-display/
Overriding Convention
Convention over Configuration
Convention over configuration is a software design paradigm used by software
frameworks that attempts to decrease the number of decisions that a
developer using the framework is required to make without necessarily losing
flexibility.
https://en.wikipedia.org/wiki/Convention_over_configuration
Departing from Convention in a View
• You can add instance variables to the as_view() in the urls.py
• You can add instance variables to the class in views.py
• You can override methods in the class in views.py
dj4e-samples/gview/urls.py
app_name = 'gview'
urlpatterns = [
path('', TemplateView.as_view(template_name='gview/main.html')),
path('cats', views.CatListView.as_view(), name='cats'),
...
]
Views
class django.views.generic.list.ListView
A page representing a list of objects. While this view is executing, self.object_list will contain the list of
objects (usually, but not necessarily a queryset) that the view is operating upon.
Method Flowchart
1. setup()
2. dispatch()
3. http_method_not_allowed()
4. get_template_names()
5. get_queryset()
6. get_context_object_name()
7. get_context_data()
8. get()
9. render_to_response()
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-display/#django.views.generic.list.ListView
dj4e-samples/gview/views.py
https://samples.dj4e.com/gview/wacky
Views
# Lets explore how (badly) we can override things...
class WackyEquinesView(generic.ListView):
model = Car
template_name = 'gview/wacky.html'
dj4e-samples/gview/templates/gview/wacky.html
<h1>List of {{ crazy_thing }}s</h1>
<p>
{% if horse_list %}
<ul>
{% for xyz in horse_list %}
<li>
<a href="{% url 'gview:horse' xyz.id %}">{{ xyz.name }}</a>
</li>
{% endfor %}
...
Summary
• Generic views allow us to produce lots of similar pages without
cutting, pasting and editing boiler plate
• Quicker development
• Consistent User Experience
• Less lines of code means fewer mistakes
Acknowledgements / Contributions
These slides are Copyright 2019- Charles R. Severance (www.dr- Continue new Contributors and Translators here
chuck.com) as part of www.dj4e.com and made available under a
Creative Commons Attribution 4.0 License. Please maintain this last
slide in all copies of the document to comply with the attribution
requirements of the license. If you make a change, feel free to add
your name and organization to the list of contributors on this page as
you republish the materials.