Django model_formset не может редактировать, сохранять или удалять информацию
Я пытаюсь создать простой modelformset для отображения нескольких копий одной и той же формы. Моя таблица models.py называется Driver и имеет только одно поле, driver:
class Driver(models.Model):
driver = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.driver if self.driver else ''
Мой urls.py:
urlpatterns = [
path('driver/', DriverCreateView.as_view(), name = "driver-create"),
]
Мой forms.py:
class DriverForm(forms.ModelForm):
class Meta:
model = Driver
fields = ['driver']
# exclude = ("id",)
DriverFormSet = modelformset_factory(Driver, form = DriverForm, fields = ['driver'], extra = 1, max_num=20, can_delete=True)
Я почти уверен, что проблема в файле views.py:
class DriverCreateView(LoginRequiredMixin, CreateView):
model = Driver
form_class = DriverForm
template_name = 'trucking/driver_form.html'
def get_context_data(self, **kwargs):
context = super(DriverCreateView, self).get_context_data(**kwargs)
context['formset'] = DriverFormSet()
return context
def post(self, request, *args, **kwargs):
formset = DriverFormSet(request.POST)
form= DriverForm(request.POST)
if formset.is_valid():
formset.save()
if self.request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if self.request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
return render(request, self.template_name, {'formset': formset})
Наконец-то мой шаблон driver_form.html:
<form method = "POST">
<fieldset class = "form-group">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
<table cellpadding="6" cellspacing="1" border="0">
<tbody>
{% for form in formset %}
{% for field in form.visible_fields %}
<tr>
<td class="column_name">{{field.label_tag}}{{field.auto_id}}</td>
<td class="column_data">{{field}}</td>
<td class="column_errors">{{field.errors|striptags}}</td>
</tr>
{% endfor %}
{% endfor %}
<tr>
<td colspan = "2" class="column_submit">
<input type="submit" name="Save_Exit" value="Save & Exit" class="submit">
<input type="submit" name="Save" value="Save" class="submit">
<a href="{% url 'database'%}"><input type="button" name="Cancel" value="Cancel" class="submit"></a>
</td>
</tr>
</tbody>
Причина, по которой я думаю, что дело в файле views.py, заключается в том, что я собрал его из нескольких различных источников, и не уверен, действительно ли строки, которые у меня есть, необходимы, или чего мне не хватает в форме, чтобы действительно обновить информацию. Когда я отредактировал функцию post
внутри представления на основе класса на form.save()
вместо formset.save()
, я смог успешно добавить новые поля, но не обновить или удалить существующие. У меня такое ощущение, что логика каким-то образом не попадает в операторы if, или набор форм сбрасывается на значение по умолчанию, возможно в этой строке:
context['formset'] = DriverFormSet()
Любой совет будет принят с благодарностью.
Вам не хватает добавления formset
скрытых входов. Эти входы обеспечивают Driver.id
для каждой формы, так что django будет знать, какой экземпляр обновлять с помощью driver
.
Вместо
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
использовать
{% for form in formset %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endfor %}
CreateView
(и все представления на основе классов) не предназначены для работы с наборами форм. Они предназначены для работы с одной формой и одним экземпляром модели. У вас будет несколько форм (через набор форм) и несколько экземпляров модели. Ваше представление будет работать, но оно не использует наилучшим образом CreateView
: вы не используете несколько методов, которые должны быть использованы, у вас будут self.object
и self.form
, которые вы никогда не будете использовать в вашем представлении.
В представлениях, основанных на функциях, нет ничего плохого. Обратитесь к django docs. Например:
@login_required
def create_drivers(request):
if request.method == 'POST':
formset = DriverFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
if request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
else:
formset = DriverFormSet()
return render(request, 'trucking/driver_form.html', {'formset': formset})