Add a URL Pattern, View, and Template for Updating a Band
Now that we've created model objects, we need to be able to update them.
Time to choose a URL pattern for our next view, which will be for updating an existing band. So far, we have:
‘bands/’ for the list of bands.
‘bands/1/’ for band 1, ‘bands/2/’ for band 2, etc.
‘bands/add/’ to create a band.
So how about ‘bands/change/’ to update a band?
We also need to know which band to change. So let’s put that into the URL too.
Therefore, it will be ‘bands/1/change/’ to update band 1, ‘bands/2/change/’ to update band 2, and so on.
Why not ‘bands/change/1/’ - with the id at the end of the URL?
That would work too! When we choose our paths, we can choose whatever parent-child structure makes sense to us. I like to imagine the change page as being a child of the band detail page. So if the detail page is at ‘bands/1/,’ I put the ‘change’ page for that band at ‘bands/1/change/.’
By now, you should know the drill, so go ahead and add a new URL pattern, view, and basic template (no form required yet) for updating a band.
Reuse a ModelForm
for Update Operations
A great thing about forms in Django is that you don’t have to create a new one specifically for the update operation - we can reuse the form we’re already using for the create operation. After all, we’re just updating the same fields that we worked with earlier.
The difference is that when we first load the view, rather than rendering an empty form, we want to pre-populate it with the existing values of the object we are editing. We do this by passing the object to the instance
keyword - e.g. , BandForm(instance=band)
. Let’s do that in the view:
# listings/views.py
def band_update(request, id):
band = Band.objects.get(id=id)
form = BandForm(instance=band) # prepopulate the form with an existing band
return render(request,
'listings/band_update.html',
{'form': form})
Then we render the form in the template:
# listings/templates/listings/band_update.html
...
<h1>Update Band</h1>
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
...
Our form is now prepopulated - for example, see http://127.0.0.1:8000/bands/1/change/:
Now we need to amend the view to update our object with the values we POST back to the server. As with our previous handlings of form POSTs, we need to handle both the GET and the POST scenarios in the view:
def band_update(request, id):
band = Band.objects.get(id=id)
if request.method == 'POST':
form = BandForm(request.POST, instance=band)
if form.is_valid():
# update the existing `Band` in the database
form.save()
# redirect to the detail page of the `Band` we just updated
return redirect('band-detail', band.id))
else:
form = BandForm(instance=band)
return render(request,
'listings/band_update.html',
{'form': form})
After updating the band with the submitted values, we redirect to the detail page of that band.
Link to the Update Page
There are two places from which we could link to a band “update” page. Let’s implement both.
First, link from the Band
list view:
# listings/templates/listings/band_list.html
...
<ul>
{% for band in bands %}
<li>
<a href="{% url 'band-detail' band.id %}">{{ band.name }}</a>
- <a href="{% url 'band-update' band.id %}">[edit]</a>
</li>
{% endfor %}
</ul>
...
Second, link from the Band
detail view:
# listings/templates/listings/band_detail.html
...
<p>{{ band.biography }}</p>
<a href="{% url 'band-update' band.id %}">Edit this Band</a>
<a href="{% url 'band-list' %}">Back to all Bands</a>
...
Now you’ve completed this chapter, check out the screencast to reinforce any of the steps you have gone over.
Now You Try! Reuse the Listing ModelForm in an “Update Listing” Page
For this exercise, you should:
Add an “Update Listing” page (URL pattern, view, and template).
Use the existing
ListingForm
in this page to update objects.Link from the
Listing
list and detail pages to the update page.
Let’s Recap!
When it comes to updating objects, you can often reuse the
ModelForm
that you use when creating objects.The difference is that when you incorporate the form, you pass the object you want to update via the
instance
keyword, e.g.,form = BandForm(instance=band)
.
Now that we’ve covered creating and updating objects, there’s one more write operation to cover - The ‘D’ in CRUD - Delete.