如果未选择任何选项,带有 ModelChoiceField(required=True) 的表单不会引发 ValidationError

Form with ModelChoiceField(required=True) doesn't raise ValidationError if no option is selected

我有一个表单,如果所有字段无效,都会引发 ValidationErrors。但是,如果没有从 ModelChoiceField 中选择任何选项,则表单都不会提交(这很好)并且 也不会在模板中引发任何 ValidationError

如果提交时没有选择类别,似乎if request.method == 'POST': returns False

# Form

class PollersForm(forms.Form):

    # Poller Category
    poller_category = forms.ModelChoiceField(widget=forms.RadioSelect(attrs={
        'class': 'poller-category-radio',
    }), queryset=Category.objects.all().order_by('category'), label='Select a Category', required=True)
# View

def raise_poller(request):
    """
    creates a new Poller object according to user inputs and redirects to it
    """
    # if this is a POST request we need to process the form data
    if request.method == 'POST':

        # create a form instance and populate it with data from the request:
        form = PollersForm(request.POST)

        # check whether it's valid:
        if form.is_valid():
            # process the remaining data in form.cleaned_data as required
            poller_category = form.cleaned_data['poller_category']

            # Get the user
            created_by = request.user

            # Save the poller to the database
            p = Poller(
                       poller_category=poller_category,
            )
            p.save()

            # Get the created object and its id to redirect to the single poller view
            created_poller = Poller.objects.get(created_by=created_by, id=p.pk)
            created_poller_id = created_poller.pk
            created_poller_slug = created_poller.slug
            poller_url = '/poller/' + str(created_poller_id) + '/' + str(created_poller_slug)

            # redirect to a new URL:
            return redirect(poller_url, request, created_poller_id)

    # if a GET (or any other method) we'll create a blank form
    else:
        form = PollersForm()

    return render(request, 'pollinator/raise_poller.html', {'form': form})
<!-- Template -->

    <form action="/raisepoller/" method="post">
        {% csrf_token %}
        {{ form.non_field_errors }}
        {{ form.errors }}

        <!-- Poller Categories -->
        <div class="fieldWrapper">
            <div class="label">{{ form.poller_category.label_tag }}</div>
            <div class="category-ctn">
                {% for category in form.poller_category %}
                    <div class="category-wrapper">{{ category }}</div>
                {% endfor %}
            </div>
        </div>

        <!-- Submit Button -->
        <button type="submit" value="Publish Poller" id="raise-poller-button">
            <div class="button-wrapper">
                <div class="button-icon"><img id="button-image" src="{% static 'images/send.png' %}"></div>
                <div class="button-text">Publish Poller</div>
            </div>
        </button>
    </form>

...呈现:

<div class="category-wrapper"><label for="id_poller_category_1"><input type="radio" name="poller_category" value="5" class="poller-category-radio" id="id_poller_category_1" required="">
 Environment</label></div>
/* CSS */

.category-wrapper input {
    position: fixed;
    visibility: hidden;
}

.category-wrapper label {
    display: inline-block;
    background-color: #fdfdfd;
    color: var(--main-darkblue-color);
    padding: 0.2vw 0.5vw;
    font-size: 1vw;
    border: 2px solid #444;
    border-radius: 4px;
    margin-bottom: 0;
}

必填=真
只检查字段中是否有东西
通过这个
您可以检查响应数据以了解该字段是否有任何默认值吗?

It seems that if request.method == 'POST': returns False if no category is selected on submit.

浏览器甚至没有发送请求,因为 HTML5 验证失败。

由于 input 上的 visibility: hidden,未显示验证消息。

.category-wrapper input {
    position: fixed;
    visibility: hidden;
}

...这会导致您的浏览器控制台中显示此错误:

❗An invalid form control with name='category' is not focusable.

改为透明、无宽度和无边距:

.category-wrapper input {
    margin: 0;
    opacity: 0;
    width: 0;
}

发生这种情况是因为视图通过了第一个 if

if request.method == 'POST':

创建表格

    # create a form instance and populate it with data from the request:
    form = PollersForm(request.POST)

然后检查它是否有效

    # check whether it's valid:
    if form.is_valid():

因为它无效,所以视图返回到第一个缩进并使用内部错误的表单呈现模板。

else:
    form = PollersForm()

return render(request, 'pollinator/raise_poller.html', {'form': form})

你能做的最好的事情就是从 else

中取出 request.method 的干净形式
form = PollersForm()

return render(request, 'pollinator/raise_poller.html', {'form': form})