Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modelformset in django generic CreateView and UpdateView

I have a model Organization with two fields 'id' and 'name'. I intend to populate it using dynamic model formsets.The code I have this far is as follows.

forms

class OrganizationForm(forms.ModelForm):
    class Meta:
        model = Organization
        fields = ('name',)

OrganizationFormset = modelformset_factory(Organization, form=OrganizationForm, fields=('name', ), extra=1)

views

class OrganizationCreate(CreateView):
    model = Organization
    form_class = OrganizationForm

    def get_context_data(self, **kwargs):
        context = super(OrganizationCreate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset()
        return context

    def post(self, request, *args, **kwargs):
        formset = OrganizationFormset(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.save()
        return HttpResponseRedirect('/')

    def form_invalid(self, formset):
        return self.render_to_response(self.get_context_data(formset=formset))


class OrganizationUpdate(UpdateView):
    model = Organization
    form_class = OrganizationForm
    template_name_suffix = '_update_form'

    def get_context_data(self, **kwargs):
        context = super(OrganizationUpdate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset()
        return context

    def post(self, request, *args, **kwargs):
        formset = OrganizationFormset(request.POST)
        if formset.is_valid():
            return self.form_valid(formset)

    def form_valid(self, formset):
        formset.save()
        return HttpResponseRedirect('/')

    def form_invalid(self, formset):
        return self.render_to_response(self.get_context_data(formset=formset))

template create

<form id="myForm" method="post" action="">
            {% csrf_token %}
            {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
           {{ form }}
           <table border="0" cellpadding="0" cellspacing="0">
               <tbody>
                   {% for form in formset.forms %}
                   {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
                   <tr>
                      <td>
                         {% if form.instance.pk %}{{ form.DELETE }}{% endif %}

                         {{ form.field1 }}
                      </td>
                      <td>{{ form.name }}</td>
                   </tr>
                   {% endfor %}
               </tbody>
           </table>
           {{ formset.management_form }}
            <input type="submit" value="Create Location">
       </form>

update

<form id="myForm" method="post" action="">
            {% csrf_token %}

           <table border="0" cellpadding="0" cellspacing="0">
               <tbody>
                   {% for form in formset.forms %}
                   {% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
                   <tr>
                      <td>
                         {% if form.instance.pk %}{{ form.DELETE }}{% endif %}

                         {{ form.field1 }}
                      </td>
                      <td>{{ form.name }}</td>
                   </tr>
                   {% endfor %}
               </tbody>
           </table>
           {{ formset.management_form }}
            <input type="submit" value="Update organizations">
       </form>

However, both the create template and the update template display pre-existing organizations while this should only be happening in the update template. Moreover, deleting pre-existing organizations in the update page returns the following error:

The view aims.views.OrganizationUpdate didn't return an HttpResponse object. It returned None instead.

I am new to django generic views and working with formsets. What I'm I doing wrong?

Thanks in advance.

like image 743
Wedava Avatar asked Apr 19 '15 06:04

Wedava


People also ask

What is Django UpdateView?

C++ Programming UpdateView is a view in Django which is used to update any model data from frontend. It is a built-in view that can be easily applied. It acts like an Admin page in updating the view.

What are Generic Views in Django?

Django's generic views were developed to ease that pain. They take certain common idioms and patterns found in view development and abstract them so that you can quickly write common views of data without having to write too much code.

What is the super class of Django form?

Django provides a Form class which is used to create HTML forms. It describes a form and how it works and appears. It is similar to the ModelForm class that creates a form by using the Model, but it does not require the Model.

What is generic editing?

Genome editing (also called gene editing) is a group of technologies that give scientists the ability to change an organism's DNA. These technologies allow genetic material to be added, removed, or altered at particular locations in the genome.


1 Answers

By default django model formsets will show any items that it can find from database. So you have to override the queryset parameter, when creating one, to let it know which items to use and when. For example, you should provide -

Organization.objects.none()

for your create view like this -

class OrganizationCreate(CreateView):
    ...

    def get_context_data(self, **kwargs):
        ...
        context['formset'] = OrganizationFormset(queryset=Organization.objects.none()) # providing none

    def post(self, request, *args, **kwargs):
        ...

    def form_valid(self, formset):
        ...

    def form_invalid(self, formset):
        ...

this will force the formset to render a blank form. Similarly change in update view to edit an specific item -

class OrganizationUpdate(UpdateView):
    ...

    def get_context_data(self, **kwargs):
        context = super(OrganizationUpdate, self).get_context_data(**kwargs)
        context['formset'] = OrganizationFormset(queryset=Organization.objects.get(pk=< get the pk from url when editing>))
        return context

    def post(self, request, *args, **kwargs):
        ...

    def form_valid(self, formset):
        ...

    def form_invalid(self, formset):
        ...

Hope this fixes your problem. If you still see the problem, then please update the question with details of urls and a possible screenshot. I will see what I can do.

like image 85
brainless coder Avatar answered Oct 17 '22 10:10

brainless coder