2

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!

7
  • Have you set the action in the form? <form action="/myview/" method="post" novalidate> ? Commented Aug 6, 2019 at 13:58
  • Thanks for your answer! Yes, i changed it right now to what you mentioned. I will get redirected, but the data will still be unchanged Commented Aug 6, 2019 at 14:13
  • is your form3.is_valid() successful ? Commented Aug 8, 2019 at 7:10
  • I think it should be Commented Aug 8, 2019 at 9:37
  • can you use python manage.py shell and try to update using command line. then you can isolate the problem to form, view or html. Also check what data is going in post request using chrome dev tools (enable preserve log in network to see the data after page change) Commented Aug 10, 2019 at 1:39

2 Answers 2

1
+50

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 %}
Sign up to request clarification or add additional context in comments.

4 Comments

Hey! I tried this, but i'm getting MultiValueDictKeyError at /mytemplate/myslug 'pk'
No by the way, i think the ID is not in the POST request
I added the HTML code that you could use to let the id of the object go into the POST data. I assumed that row in the template is an istance of MyModel, so it has a pk attribute.
I still don't see the field updating, i really don't know why. Instead of pk, i'm using id. If i try to add a line {{ row.id }} i can see the id of that record, so that part is working, i think that there is still something i'm missing in the view, possibly
1

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,})

2 Comments

Hey, thanks for your help. I just don't understand, what should i put instead of slug=slug
you should put exactly that slug=slug plus slug parameter in function definition def myview(request, tvticker, slug): i added slug to your parameters

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.