#What's a good strategy for submitting multiple forms of the same type in a single view?

5 messages · Page 1 of 1 (latest)

visual oar
#

I have a dialog that allows a user to create a new Cage object. In the same dialog, a user may also create new Mice that will automatically be assigned to that Cage (via a foreign_key field). I would like for it to be possible that multiple Mice can be created at the same time, using the same form if possible. I have previously implemented the singular version of this form (i.e. create one animal at a time). It would be nice to re-use this form:

#

forms.py

class CreateMouseForm(forms.Form):
    form_title = forms.CharField(initial = "CreateMouseForm", required = False)
    birth_date = forms.DateField(help_text = "date of birth", label = "birthdate", initial = datetime.date.today())
    mouse_id = forms.CharField(help_text = "", label = "mouse ID")
    genotype = forms.CharField(help_text = "", label = "genotype")
    sex = forms.ChoiceField(choices = Sex.choices)

    cages: List[str] = []
    for idx, c in enumerate(Cage.objects.all()):
        cages.append((c.cage_id, c.cage_id)) # form.ChoiceField.choices expects tuple with contents (value, display)

    cage = forms.ChoiceField(choices = cages)

    # Magic Methods - called when self.cleaned_data[attr] is called 
    def clean_cage(self):
        fk = Cage.objects.get(cage_id = self.cleaned_data['cage'])
        return fk
#

I also created this helper function in views.py to handle the bound form:

views.py

def handleBoundCreateMouseForm(request: HttpRequest) -> None:
   form: CreateMouseForm = CreateMouseForm(request.POST)

   # change to try-except
   if form.is_valid():
      m: models.Mouse = models.Mouse()
      m.birth_date = form.cleaned_data['birth_date']
      m.fk_cage = form.cleaned_data['cage']
      m.genotype = form.cleaned_data['genotype']
      m.mouse_id = form.cleaned_data['mouse_id']
      m.sex = form.cleaned_data['sex']
      m.save()
   else: 
      print("form invalid, ", form.errors)
#

Finally, here is the template that creates a Cage and Mice at once:

{% extends "generics/generic-dialog.html" %}
{% block dialog_content %}
    {% load static %} <link rel = "stylesheet" href = "{% static 'css/components/cage-create-dialog.css' %}">
    <form action="" method="POST">
        {% csrf_token %}
        <div class = "cage-create-dialog-container">
            <div class = "cage-create-dialog-field">
                {{ create_cage_form.form_title.as_hidden }}
                <div>
                    Cage ID
                </div>
                <div>
                    {{ create_cage_form.cage_id }}
                </div>
            </div>
            <div class = "cage-create-dialog-field">
                <div>
                    Cage Type
                </div>
                <div>
                    {{ create_cage_form.cage_type }}
                </div>
            </div>
        </div>
        <div class = "cage-create-add-mouse">
            <div class = "cage-create-dialog-field">
                {{ create_mouse_form.form_title.as_hidden }}
                <div>Mouse ID</div>
                <div>{{ create_mouse_form.mouse_id }}</div>
            </div>
            <div class = "cage-create-dialog-field">
                <div>Sex</div>
                <div>{{ create_mouse_form.sex }}</div>
            </div>
            <div class = "cage-create-dialog-field">
                <div>DOB</div>
                <div>{{ create_mouse_form.birth_date }}</div>
            </div>
            <div class = "cage-create-dialog-field">
                <div>Genotype</div>
                <div>{{ create_mouse_form.genotype }}</div>
            </div>
        </div>
        <input type = "submit" value = "Submit">
        <input type = "button" value = "Cancel" onclick = "$(this).parents('dialog')[0].close()">
    </form>
{% endblock dialog_content %}
hollow hound
#

Sounds like inline modelformset