Make inlineformset in django required

做~自己de王妃 提交于 2020-01-14 14:13:13

问题


I am new to django (until now, I used the symfony PHP Framework). My problem is this: I have a model Event and model Date. The Date has a foreign key to Event, so that an Event may (or should) have one or more Dates.

Now I want to have a form to create Events and this form should include a subform for adding one corresponding Date (more dates should be added later, if the Event has more than one date).

I used the inlineformset to realize the Date subform, but if no Date is being entered, no error occurs and the Event is being saved without a Date. All I want is to make this inlineformset required or to say, that there has to be at lease (and only) one inlineformset.

I found these questions, but none of the answers helped me:

  • Inline Form Validation in Django
  • Django formsets: make first required?

Any hints for me?

EDIT: I need this for the frontend, not for the backend. The first link covers it for the admin backend.

EDIT2: Some sourcecode added

MandatoryInlineFormSet.py:

from django.forms.models import BaseInlineFormSet
from django import forms

class MandatoryInlineFormSet(BaseInlineFormSet):
    def clean(self):
        # get forms that actually have valid data
        count = 0
        for form in self.forms:
            try:
                if form.cleaned_data:
                    count += 1
            except AttributeError:
                # annoyingly, if a subform is invalid Django explicity raises
                # an AttributeError for cleaned_data
                pass
        if count < 1:
            raise forms.ValidationError('You must have at least one order')

event.py:

from [...]
def new(request):
    DateFormset = inlineformset_factory(
            Event,
            Date,
            can_delete=False,
            extra=1,
            max_num=1,
            formset=MandatoryInlineFormSet,
            )

    if request.POST:
        form = EventForm(request.POST)
        date_formset = DateFormset(request.POST)
        if form.is_valid():
            event = form.save(commit=False)
            date_formset = DateFormset(request.POST, instance=event)
            if date_formset.is_valid():
                event.save()
                date_formset.save()
                return HttpResponseRedirect(reverse('frontpage'))
    else:
        form = EventForm()
        date_formset = DateFormset()
    return render_to_response('event/new.html', {
        'form': form,
        'date_formset': date_formset,
        }, context_instance=RequestContext(request))

event/new.html:

[...]
<form action="{% url new-event %}" method="post">
    {% csrf_token %}
    {{ form.as_p }}

    {{ date_formset.management_form }}
    {% for date_form in date_formset.forms %}
        {{ date_form.as_p }}
    {% endfor %}


    <input type="submit" value="{% trans "Create event" %}"/>
</form>
[...]

Best regards, sewid


回答1:


I've tripped over this myself almost by accident. I had an inline formset which had a modelchoicefield on it. That modelchoice had no empty_label. So it technically wasn't entirely blank. When other fields were left out on the inline form it would show validation errors (you can easily test for this in the view and not save the main form unless all the inline forms are valid).

So, it seems you are left with two options: 1) populate the date form with invalid text (i.e. not a date, "helper" text of some kind) that when left in there and submitted it fails to validate, or 2) rework your date selector to dropdown widgets that have no blank state - thus forcing the user to pick something (but you might prefer a proper javascript date widget, which would make multiple dropdowns onerous.



来源:https://stackoverflow.com/questions/3901931/make-inlineformset-in-django-required

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!