0

Here is the situation:

I have a model as below:

class School(Model):
        name = CharField(...)

Permit model has three objects:

School.objects.create(name='school1')  # id=1
School.objects.create(name='school2')  # id=2

I have another model:

Interest(Model):
    school_interest = ManyToManyField(School, blank=True,)

I then build a ModelForm using Interest:

class InterestForm(ModelForm):
    school_interest = ModelMultipleChoiceField(queryset=School.objects.all(), widget=CheckboxSelectMultiple, required=False)
    class Meta:
        model = Interest
        fields = '__all__'

I have a view:

def interest(request):
    template_name = 'interest_template.html'
    context = {}
    if request.POST:
        interest_form = InterestForm(request.POST)
        if interest_form.is_valid():
             if interest_form.cleaned_data['school_interest'] is None:
                return HttpResponse('None')

             else:
                return HttpResponse('Not None')
     else:
        interest_form = InterestForm()
     context.update({interest_form': interest_form, })
     return render(request, template_name, context)

and in interest_template.html I have:

<form method="post">
    {% csrf_token %}
    {{ interest_form.as_p }}
<button type="submit">Submit</button>
</form>

I expect to see None when I check no one of the form fields and submit it.

I expect to see 'Not None' when I check any or all of the form fields and submit the form.

However, I do not see what I expect to happen.

Amin Ba
  • 1,603
  • 1
  • 13
  • 38
  • You should check with `request.method == 'POST'`. A POST request can still contain no data, hence `request.POST` is empty, but the method is still POST. – Willem Van Onsem Jul 26 '19 at 09:05
  • ``` if request.POST ``` is equal to ``` if request.METHOD == 'POST' ``` So I already have checked the method is POST and then go to other conditions – Amin Ba Jul 26 '19 at 10:30
  • no, this is incorrect. `if request.POST` checks the truthiness of the `QueryDict` that `POST` has. You can for example use `curl` to make a `POST` request without data, like `curl -XPOST '127.0.0.1:port/endpoint'`. The `request.method == 'POST'` will succeed, but `request.POST` as condition will fail, because you did not send any POST data with the request. It is even possible, but bad design, than a POST request has `request.GET` data for example. – Willem Van Onsem Jul 26 '19 at 10:33
  • see for example https://stackoverflow.com/q/30518576/67579 and https://stackoverflow.com/questions/22651044/if-request-method-post-false-but-if-request-post-true-why-dj – Willem Van Onsem Jul 26 '19 at 10:34
  • What I understood is that a request's Method can be something other than POST but still ```if request.POTS``` contains POST and turns out True. right? – Amin Ba Jul 26 '19 at 10:37
  • 1
    no it is the opposite way. Even if the method is a POST method, `if request.POST` can fail, since a POST request does not per se contains data in the header of the HTTP request. – Willem Van Onsem Jul 26 '19 at 10:38
  • Or You mean a request might be POST but because the POST is empty, ```if request.POST``` turns out to be False – Amin Ba Jul 26 '19 at 10:38
  • I understood!! Thank you! – Amin Ba Jul 26 '19 at 10:39
  • exactly, therefore `if request.POST` is not sufficient. Especially since a successful POST usually should result in a redirect, due to the [Post/Redirect/Get pattern](https://en.wikipedia.org/wiki/Post/Redirect/Get). – Willem Van Onsem Jul 26 '19 at 10:39

1 Answers1

1

I changed my view to this and it worked:

def interest(request):
    template_name = 'interest_template.html'
    context = {}
    if request.POST:
        interest_form = InterestForm(request.POST)
        if interest_form.is_valid():
             if not interest_form.cleaned_data['school_interest']:
                return HttpResponse('None')
             else:
                return HttpResponse('Not None')
     else:
        interest_form = InterestForm()
     context.update({interest_form': interest_form, })
     return render(request, template_name, context)
Amin Ba
  • 1,603
  • 1
  • 13
  • 38