Jack022
Jack022

Reputation: 1257

Update DB data through form in django

I'm trying to add a form on my page that will update a certain field in my DB.

This is what the template looks like:

{% for row in mydb %}
  <form action="/myview/{{myslug}}/" method="post" novalidate>
    {% csrf_token %}
    {% include 'main/includes/bs4_form.html' with form=form3 %}
      {{row.firstfield}}
      {{row.secondfield}}
      <button name="button3" type="submit" class="btn btn-danger style="background-color: red;">CANCEL</button></td>
  </form>
{% endfor %}

The for statements is to display each row of the data in my table in a single line. Near each line, there is a submit button. When this button is clicked, the field secondfield is updated with the value New Value, as you can see in my form.

Thi is the part of the view involved:

def myview(request, tvticker):
  row = mydb.objects

  if request.method == 'POST':

  ...
      if 'button3' in request.POST:
        form3 = form = UpdateForm(request.POST)
        if form3.is_valid():
          profile = form.save(commit=False)
          profile.save()
          messages.success(request, f"Success")
  ...

   render(request, "main/mytemplate.html", 
          context={'row': row,})

And here is the form:

class UpdateForm(forms.ModelForm):

    SomeField = forms.CharField()
    class Meta:
        model = MyModel
        fields = ("SomeField",)

    def save(self, commit=True):
        send = super(UpdateForm, self).save(commit=False)
        send.secondfield = 'New Value'
        if commit:
            send.save()
        return send

My actual code it's not working, is seems to send a POST request but the secondfield value is not updated. For example, if i click the submit button of the second record in my template.html, the secondfield value of that record should be changed from oldvalue to newvalue. At the moment, the value is not updated.

Any advice is appreciated, thanks in advance!

Upvotes: 2

Views: 1226

Answers (2)

Mohammad Moallemi
Mohammad Moallemi

Reputation: 658

you should use

UpdateForm(request.POST, instance=instance)

syntax as said before this post when you have id or slug in your url pattern you can pass it to your view function like this:

def view_function(request, pk, slug)

so no need to pass it in form data

one more problem i see in your code is that you call:

form3.is_valid()

but then try to save

profile = form.save(commit=False)

you validate "form3" but then try to save "form" you must call .is_valid() before you can save a form .is_valid() creates cleaned_data but here you don't validate "form" or save "form3"

try this code below it should solve your problem if not please post all of exception info and traceback

def myview(request, tvticker, slug):
    row = mydb.objects

    if request.method == 'POST':
        if 'button3' in request.POST:
            instance = get_object_or_404(MyModel, slug=slug)
            form3 = form = UpdateForm(request.POST, instance=instance)
            if form3.is_valid():
                # here i save form3 instead of form that is not validated
                profile = form3.save(commit=False)
                profile.save()

   render(request, "main/mytemplate.html",
          context={'row': row,})

Upvotes: 1

Augusto Destrero
Augusto Destrero

Reputation: 4345

I cannot see how you pass the id (that is the primary key) of the record you want to update to the view. Is it in the post data?

You should remember that the ModelForm constructor has an attribute instance that should be used to pass an existing object you want to update when calling the save() method of the ModelForm itself.

You are not using an instance attribute in the UpdateForm constructor, so that could be the problem for your record not updating as you expect.

Assuming that the id of the record you want to update is in the POST data with the name pk you could write something like this:

if 'button3' in request.POST:
    instance = MyModel.objects.get(pk=request.POST['pk'])
    form3 = form = UpdateForm(request.POST, instance=instance)
    if form3.is_valid():
        profile = form.save(commit=False)
        profile.save()

This is the HTML that you could use to let the id of the record go in the POST data:

{% for row in mydb %}
    <form action="/myview/{{myslug}}/" method="post" novalidate>
    {% csrf_token %}
    <input type="hidden" name="pk" value="{{ row.pk }}">
    {% include 'main/includes/bs4_form.html' with form=form3 %}
    {{row.firstfield}}
    {{row.secondfield}}
    <button name="button3" type="submit" class="btn btn-danger style="background-color: red;">CANCEL</button></td>
    </form>
{% endfor %}

Upvotes: 1

Related Questions