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.
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.
Your post method returns nothing when formset is invalid in both Class based views (create and update), you should return form_invalid
in else
branch:
if formset.is_valid():
return self.form_valid(formset)
else:
return self.form_invalid(formset)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.