Update/Edit database content with form

Hi everyone !

I’m trying to edit/update some content through a form :

<div id="products">
{% for product in ProductModel %}
<div class="product_box">
    <label type="text">Product Name : <a href="{% url 'products:details' product.id %}">{{ product.product_name}}</a></label>
    <br>
    <label type="text">Product Description : {{ product.product_description}}</label>
    <br>

    <div class="product_box_controls">
        <input type="button" value="Edit">
        <input type="button" value="Delete">
    </div>
</div>
{% endfor %}

I’d like to use the following “edit” view when I hit the “Edit” button :

def edit(request, product_id):
if(request.method == "PUT"):
    form = ProductForm(request.PUT)

    if(form.is_valid):
        form.save()

else:
    form = ProductForm()

template_name = "products/edit.html"
context = {
    "ProductForm":ProductForm,
    "ProductModel":ProductModel.objects.get(id=product_id),
}

return render(request,template_name,context)

I couldn’t find Django documentation regarding the PUT method but instead just GET and POST, so how to proceed ?

Thank you in advance :slight_smile:

Web browsers only send form data in the body for POST, or in the url parameters for GET, so you can’t use PUT for forms. See ‘method’: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form

There’s no Django documentation for such a request attribute because it doesn’t exist.

Hi @adamchainz, thanks for your answer !

Ok ! I thought there were GET POST PUT and DELETE HTTP methods

There are - there are actually others as well (HEAD, CONNECT, OPTIONS, PATCH are the others I can think of).

But, in the context of a browser form, only GET and POST are valid. Most (all?) browsers will actually translate a “PUT” to a “GET”.

The other verbs are more typically used for API-style activities, where the requesting user is a program other than a browser. (e.g. a custom client, such as one written using the python requests library.)

From:

Allowed in HTML forms No

Hi @KenWhitesell ! Thanks again for your help

Got it !

But I’m working on this “edit” view and just get :

Exception Type:	ValueError
Exception Value:	
The ProductModel could not be changed because the data didn't validate.

views.py

def edit(request, product_id):
product = ProductModel.objects.get(id=product_id)

if(request.method == "POST"):
    form = ProductForm(request.POST, instance=product)

    if(form.is_valid):
        form.save()
        return redirect("/")

else:
    form = ProductForm()

template_name = "products/edit.html"
context = {
    "ProductForm":ProductForm,
    "ProductModel":ProductModel.objects.get(id=product_id),
}

return render(request,template_name,context) 

edit.html

{% extends "base.html" %}

{% block page_title %}Products : {{ product.product_name }}{% endblock %}

{% block page_content %}
<form id="updateProductForm" action="" method="POST">
    {% csrf_token %}
    <label type="text" >Product Name : </label>
    {{ ProductForm.product_name }}
    <br>
    <label type="text" >Product Description : </label>
    {{ ProductForm.product_description }}
    <br>
    <input type="submit" value="Update">
</form>
{% endblock %}

Thank you in advance

Your code does not actually call is_valid. It’s missing the parenthesis after the method name. Because is_valid is a method, if form.is_valid: will evaluate to True always.

I’d suggest that you be sure to read error messages carefully. It will usually provide good guidance to where your problem is located. Also, in my experience, copying the exact error message into a search engine often produces solutions to problems that I’m encountering. Those things might save you time in the future so you don’t have to wait around for people on a forum to answer. Hope that helps.

1 Like

Couple items of general note too:

  • When you’re posting code, please enclose it within a line of three “back-tick” characters (`) such that the code will look like this:
def edit(request, product_id):
    product = ProductModel.objects.get(id=product_id)
    if(request.method == "POST"):
    form = ProductForm(request.POST, instance=product)
else:
    form = ProductForm()

rather than using the “preformatted text” block:

def edit(request, product_id):
    product = ProductModel.objects.get(id=product_id)

    if(request.method == "POST"):
        form = ProductForm(request.POST, instance=product)
    else:
        form = ProductForm()

If nothing else, it makes the code easier to scan.

  • Including both the model and the form in cases like this would be extremely helpful.

  • From a general Python-styling note, it’s traditional that classes are named with capitalized words, but instances are lower-case words separated by underscores. (ProductForm would be a reference to the form class itself, product_form would be an instance of that class.)

  • Hopefully you’re running this with DEBUG=True in your settings file - if you are, you should be getting a lot more useful information in your browser than just the validation error you’re reporting here.

1 Like

Hi @mblayman ! Definitely True ! Thanks a lot !