opportunity356
opportunity356

Reputation: 168

Django form is not valid because of empty POST

My django form is not valid. I guess it occurs because request.POST is almost empty(only csrf_token is included). Still I can't find the reason. Seeking for a help.

P.S. (To make it clear, what's happening in code) I have three levels of cascading categories and a list of patterns. I want to mark all the patterns with one category. Options of select2 depend on the selected option in select1. The same thing is for select3.

The form:

class AddPatternForm(forms.Form):
    category_1 = forms.ChoiceField()
    category_2 = forms.ChoiceField(required=False)
    category_3 = forms.ChoiceField(required=False)
    patterns = forms.CharField()

    def verify(self):
        valid = []
        invalid = []
        patterns = self.patterns.split('\n')
        for pattern in patterns:
            if VALID_DOMAIN.match(pattern):
                valid.append(get_domain(pattern))
            elif VALID_REGEXP.match(pattern):
                valid.append(pattern)
            else:
                invalid.append(pattern)
        return valid, invalid

The view:

def add_pattern(request):
    patterns = Url.objects.all()
    parents = Category.objects.filter(parent=None)
    if request.method == 'POST':
         form = AddPatternForm(request.POST)
         if form.is_valid():
             valid, invalid = AddPatternForm.verify()
             if form.category_3:
                 parent_id = form.category_3
             elif form.category_2:
                 parent_id = form.category_2
             else:
                 parent_id = form.category_1
             parent = Category.objects.get(pk=parent_id)
             for pattern in valid:
                 Url(pattern=pattern, categories=parent).save()
             return HttpResponseRedirect('')
     else:
         form = AddPatternForm()

     return render(request, 'app/add_pattern.html', {
        'form': form,
        'patterns': patterns,
        'parents': parents,
    })

The html:

      <form id="chooseCategory" method="post" action="">
        {% csrf_token %}
        <div class="form-group">
          <h2 id="chosenCategory">Категория: </h2>
          <select id="select1" class="form-control">
            <option value="">---</option>
            {% for parent in parents %}
            <option value="{{ parent.id }}">
              {{ parent }}
            </option>
            {% endfor %}
          </select>
            <option value="">---</option>
          <select id="select2" class="form-control">
          </select>
            <option value="">---</option>
          <select id="select3" class="form-control">
          </select>
        </div>
        <div class="form-group">
          <textarea class="form-control" rows="5"></textarea>
        </div>
        <button type="submit" class="btn btn-default">Save</button>
      </form>

The JS (realization of cascading dropdown select):

$( "#select1" ).change(function () {
          var str = "Категория: ";
          $( "#select1 option:selected" ).each(function() {
            str += $( this ).text() + " ";
          });
          $( "#chosenCategory" ).text( str );
          $( "#select2" ).find('option').remove().end()
          $( "#select2" ).append("<option value=''>---</option>")
          $.get("/load_new_options/", {"parent_id": $( "#select1 option:selected" ).val()},
          function(data) {
            var c = JSON.parse(data);
            for (i in c) {                
              $( "#select2" ).append("<option value='" + c[i].pk + "'>" + c[i].fields.name + "</option>")
            }
          })
        })
        .change();


        $( "#select2" ).change(function () {
          var str = "Категория: ";
          $( "#select2 option:selected" ).each(function() {
            str += $( this ).text() + " ";
          });
          $( "#chosenCategory" ).text( str );
          $( "#select3" ).find('option').remove().end()
          $( "#select3" ).append("<option value=''>---</option>")
          $.get("/load_new_options/", {"parent_id": $( "#select2 option:selected" ).val()},
          function(data) {
            var c = JSON.parse(data);
            for (i in c) {                
              $( "#select3" ).append("<option value='" + c[i].pk + "'>" + c[i].fields.name + "</option>")
            }
          })
        })
        .change();

        $( "#select3" ).change(function () {
          var str = "Категория: ";
          $( "#select3 option:selected" ).each(function() {
            str += $( this ).text() + " ";
          });
          $( "#chosenCategory" ).text( str );
        })
        .change();

        $('#chooseCategory').cascadingDropdown({
            selectBoxes: [
                {
                    selector: '#select1',
                },
                {
                    selector: '#select2',
                    requires: ['#select1'],
                },
                {
                    selector: '#select3',
                    requires: ['#select1', '#select2'],
                    requireAll: true,
                    onChange: function(){
                    }
                }
            ]
        });

UPD The form is still not valid. The form.errors look as follows:

category_3
Select a valid choice. 19 is not one of the available choices.
category_2
Select a valid choice. 4 is not one of the available choices.
category_1
Select a valid choice. 1 is not one of the available choices.

Upvotes: 0

Views: 497

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599480

Don't guess. Output the errors in the template, then you'll know why it is not valid.

{{ form.errors }}

Edit You have not put any name attributes in your form field elements. Browsers only send data on a form submit if the field has a name, as that's what the data is associated with.

You really should be using the Django form to output the fields anyway, rather than creating the HTML manually.

Upvotes: 1

Related Questions