1

Edit: I seem to have figured out the next step in fixing this, as the actual name for each variable in the payload needs to be how I set it to be in forms. Will update if I solve it. Additionally, if I change it to a GET request, it works fine, but I have no idea why Django does not work with the POST request.

Need some help with this. If I pass a formset to a html template and request its payload with a POST request, I get this error

Field Error: primary <ul class="errorlist"><li>This field is required.</li></ul> Field Error: symbol <ul class="errorlist"><li>This field is required.</li></ul> Field Error: secondary <ul class="errorlist"><li>This field is required.</li></ul>

For the formset, the forms are dynamically added or deleted onto the page, but there will always be a single form on the page when the page is loaded. And for the other dynamically added forms, they get the same error as well. But when I pass a single form to the html template, I get the POST payload just fine.

views.py

def advanced(request):

    form = formset_factory(Search)
    if request.method == 'POST':
        formset = Search(request.POST)
        for field in formset:
            print("Field Error:", field.name,  field.errors)
    return render(request,"advancedsearch.html", {"formset":form})
forms.py

indicator = [
    ('', ''),
    ('high', 'Estimated high'),
    ('low', 'Estimated low'),
    ('median', 'Estimated median'),
    ('realprice', 'Real Price'),
    ]

symbol= [
    ('', ''),
    ('>', 'higher than'),
    ('<', 'less than'),
    ('=', 'equal to'),
    ]


class Search(forms.Form):
    primary = forms.CharField(label='a', widget=forms.Select(choices=indicator))
    symbol =  forms.CharField(label='b', widget=forms.Select(choices=symbol))
    secondary = forms.CharField(label='c', widget=forms.Select(choices=indicator))
advancedsearch.html

<form method="POST" action="">{% csrf_token %}
  {% for x in formset %}
    <div class = "d-flex flex-row justify-content-center bd-highlight mb-5">
      {{ x.as_p }}
    </div>
  {% endfor %}    
  <button type="submit" class="btn btn-primary" >Search</button>
</form>
Form Data example
csrfmiddlewaretoken: Sc2bMfDJr2qQ9rqeOxd3YnVpB37d36ZkQ85OfGaUL7vD61IyGzNiVDn6c5vydKSX
form-0-primary: low
form-0-symbol: >
form-0-secondary: low
sal1200
  • 11
  • 3
  • `But when I pass a single form to the html template, I get the POST payload just fine.` , how do you get the payload? – Yang Jun 20 '22 at 02:24
  • Search(request.POST). The same I used for the formset – sal1200 Jun 20 '22 at 02:30
  • I guess that's because when you did the POST method, more than one form been post and not all of the fields in each form been filled, so the error happened. What if you seperate them into each unique form, does it help? – Yang Jun 20 '22 at 02:37
  • Each form will always be filled upon creation, and separating them into their own unique form could work, but I want them to be submitted together. – sal1200 Jun 20 '22 at 02:46
  • You aren't actually even using your formset! `form = formset_factory(Search)` and then you say `formset = Search(request.POST)` which basically means you instantiate your _form class_ instead of the formset class (Which you name as `form` above). Also note `formset_factory` creates a _class_ you need to instantiate it, although your code works in rendering the formset but it relies on the coincidence that the template implicitly calls anything that is callable – Abdul Aziz Barkat Jun 20 '22 at 12:22

1 Answers1

0

Two ways came up in mind for this.

  1. Switch form.CharField to form.ChoiceField
# forms.py

...

class Search(forms.Form):
    primary = forms.CharField(label='a', widget=forms.Select(choices=indicator))
    symbol =  forms.CharField(label='b', widget=forms.Select(choices=symbol))
    secondary = forms.CharField(label='c', widget=forms.Select(choices=indicator))
  1. Ture form field required to False, check this question
Yang
  • 218
  • 3
  • 9