3

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:

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

Community
  • 1
  • 1
sewid
  • 341
  • 1
  • 3
  • 7
  • Why doesn't my answer to the first linked question help? It would seem to be the answer to exactly your problem. – Daniel Roseman Oct 10 '10 at 21:06
  • Because it's for the admin backend, I need this functionality in the frontend (I forgot to mention this). I tried to use your code for the frontend, but it didn't work. – sewid Oct 11 '10 at 04:21
  • I can't see why that wouldn't work outside the admin. Just create the inlineformset in your views code. – Daniel Roseman Oct 11 '10 at 06:29
  • I tried it, but there is no error message, when I left the inlineformset empty. I'm not at home right now, when I'm back home, I will post my code. – sewid Oct 11 '10 at 16:14
  • Ok, I added the sourcecode. Problem is, when leaving the inlineformset blank and submitting the form, no error occurs, the event gets saved. If there is another error in the event form, the error is marked, the event is not saved, but the inlineformset has no error again. – sewid Oct 11 '10 at 18:25

1 Answers1

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.

JohnO
  • 1,889
  • 1
  • 12
  • 15