View are something that accepts a request, and returns some kind of a response.
In the render()
function, you can pass a context
that are variables you can pass to your template.
how to add a new view
- define the URL in
your-project/your-app/urls.py
- add a view in
your-projects/your-app/views/new-view.py
- import the view in
your-projects/your-app/views/__init__.py
shortcuts: render, redirect
from django.shortcuts import render, redirect
def index(request):
students = Students.objects.all()
context = { "students": students }
return render("index.html", context)
def new(request):
# save a new student
return redirect("your_app:new")
Note that you can't pass a context with a redirect
; you can only pass a URL and query parameters.
messages
https://docs.djangoproject.com/en/4.1/ref/contrib/messages/#using-messages-in-views-and-templates
If you want to use "messages" (e.g. flash messages, toast messages in other frameworks), you can use the messages framework.
Add this import,
from django.contrib import messages
... and call the messages like this in your views.
messages.debug(request, '%s SQL statements were executed.' % count)
messages.info(request, 'Three credits remain in your account.')
messages.success(request, 'Profile details updated.')
messages.warning(request, 'Your account expires in three days.')
messages.error(request, 'Document deleted.')
The template can show the messages like this:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
It' s important to iterate all the messages, otherwise the messages will not be cleared.
from django.contrib import messages
# view to create new student
def new(request):
if request.method == "POST":
# do something with the form
student.save()
# send messages
messages.success(request, "saved student")
formsets
You can use formsets when you want to handle multiple records of the same model (e.g. multiple students).
Formsets come in handy because they will do the validation on all the records for you.
In your view, you can define your formset like this:
# your_project/your_app/views/new.py
from django.forms import modelformset_factory
from django.shortcuts import redirect, render
from your_app.models import Student
def new(request):
# fields: defines which fields to show in the form
# extra: defines how many extra rows you want in the form, on top of existing records
StudentFormset = modelformset_factory(Student, fields=["last_name", "first_name", "photo"], extra=10)
if request.method == "GET":
# by default, formset will populate all records in that model
# specify the set of records to be "no students"
formset = StudentFormset(query=Student.objects.none())
context = { "formset": formset }
return render("your_app/new.html", context)
if request.method == "POST":
# populate the formset with user input
formset = StudentFormset(request.POST, request.FILES)
if formset.is_valid():
# save the entire formset
formset.save()
# make sure to redirect after a POST request
return redirect("your_app:new")
If you need to specify a foreign key on a formset, you do have to iterate through each record like so:
# your_project/your_app/views/new.py
if formset.is_valid():
# get the instances via the save method
# but don't commit yet
instances = formset.save(commit=False)
for student in instances:
student.school_id = 1
# populate school_id and save one by one
student.save()
In this case, an "atomic transaction" might be needed, where if either all transactions succed, or no transaction succeeds.
You can use the decorator or the with:
block (please see the documentation for the latter option; I prefer decorators with less indent).
# define a helper function with a decorator
from django.db import transaction
@transaction.atomic
def save_students_with_school(formset, school_id):
instances = formset.save(commit=False)
for student in instances:
student.school_id = school_id
# populate school_id and save one by one
student.save()
# call them in your view like this
if formset.is_valid():
# call the atomic transaction
save_students_with_school(formset, 1)
Top comments (0)