• Multi-Object-Edit With Django FormSets


    I had to write a multi-object edit table the other day for a Django project and as such I dove into the FormSet Documentation. Django’s documentation is really good usually but the part abut the FormSets was a bit of a letdown.

    So in case anybody else is in the same situation here is some code of how I did it (written from memory - should still be okay I hope).

    # forms.py
    from django import forms
    from django.forms.models import modelformset_factory
    
    # creating a FormSet for a specific Model is easy
    FooFormSetBase = modelformset_factory(
      Foo, extra=0, fields=('somefield', 'someotherfield'))
    
    # now we want to add a checkbox so we can do stuff to only selected items
    class FooFormSet(FooFormSetBase):
      # this is where you can add additional fields to a ModelFormSet
      # this is also where you can change stuff about the auto generated form
      def add_fields(self, form, index):
        super(FooFormSet, self).add_fields(form, index)
        form.fields['is_checked'] = forms.BooleanField(required=False)
        form.fields['somefield'].widget.attrs['class'] = 'somefieldclass'
    

    After writing the FormSet itself here is the view:

    # views.py
    from django.shortcuts import redirect
    from django.template import RequestContext
    from fooproject.fooapp.forms import FooFormSet
    from fooproject.models import Foo
    
    
    def fooview(request):
      if request.method == 'POST':
        # we have multiple actions - save and delete in this case
        action = request.POST.get('action')
        formset = FooFormSet(
          request.POST, queryset=Foo.objects.all())
    
        if formset.is_valid():
          # iterate over all forms in the formset
          for form in formset.forms:
            # only do stuff for forms in which is_checked is checked
            if form.cleaned_data.get('is_checked'):
              if action == u'delete':
                # we need to call save to get an actual model but
                # there is no need to hit the database hence the
                # commit=False
                model_instance = form.save(commit=False)
                # now that we got a model we can delete it
                model_instance.delete()
              if action == u'save':
                form.save()
    
          redirect('someview')
    
      else:
        formset = FooFormSet(queryset=Foo.objects.all())
    
      return render_to_response('sometemplate.html', {'formset': formset},
        context_instance=RequestContext(request))
    

    Now all that’s missing is the template:

    <form action="." method="post" accept-charset="utf-8">
      <table>
        <thead>
          <tr>
            <th>is_checked</th>
            <th>somefield</th>
            <th>someotherfield</th>
          </tr>
        </thead>
        <tbody>
        {% for form in formset.forms %}
          <tr>
            <td>
              {# don't forget about the id field #}
              {{ form.id }}
              {{ form.is_checked }}
            </td>
            <td>{{ form.somefield }}</td>
            <td>{{ form.someotherfield }}</td>
          </tr>
        {% endfor %}
        </tbody>
      </table>
      <p>
        {# and don't forget about the management form #}
        {{ formset.management_form }}
        {% csrf_token %}
        <button type="submit" name="action" value="save">save</button>
        <button type="submit" name="action" value="delete">delete</button>
      </p>
    </form>
    

    Of course there is stuff still missing – you won’t see errors in your form for example. But you get the general idea.

  • 相关阅读:
    洛咕 P4474 王者之剑
    CF708D Incorrect Flow
    CF802C Heidi and Library (hard)
    CF434D Nanami's Power Plant
    洛咕3312 [SDOI2014]数表
    洛咕 P3704 [SDOI2017]数字表格
    洛咕 P3706 [SDOI2017]硬币游戏
    洛咕 P4491 [HAOI2018]染色
    Luogu4240 毒瘤之神的考验 莫比乌斯反演、根号分治
    UOJ269 清华集训2016 如何优雅地求和 下降幂多项式、NTT
  • 原文地址:https://www.cnblogs.com/floodwater/p/10024547.html
Copyright © 2020-2023  润新知