• 12 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 7/20/22

Update a Model Object With a ModelForm

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/:

The fields of the Update Band page are filled in.
Our form is prepopulated.

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>
...
Next to each band is the option
"Edit" links added.

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>
...
At the bottom of the page is a link titled
"Edit this Band" added.

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.

Example of certificate of achievement
Example of certificate of achievement