下面的模型Entry
和Meaning
具有多对多关系。我需要创建一个更新表单/视图,以便同时编辑Entry
和Meaning
个对象。我还可以在编辑时向Meaning
对象添加更多Entry
个对象。
我尝试使用UpdateView
和modelformset_factory
,如下所示。
我可以看到表单,但我的观点并没有保存Meaning
更改。我有两个问题:
如何保存Meaning
更改?
如何在此表单/视图中添加或删除Meaning
个对象?
class Entry(models.Model):
title = models.CharField(max_length=70)
slug = models.SlugField('slug', max_length=100, unique=True)
class Meaning(models.Model):
title = models.CharField(max_length=70)
language = models.CharField(max_length=5, choices=LANGUAGE_CHOICES)
entry = models.ManyToManyField(
Entry, related_name='meaning',
related_query_name='meanings',
through='MeaningRelation')
class MeaningRelation(models.Model):
entry = models.ForeignKey(Entry, on_delete=models.CASCADE)
meaning = models.ForeignKey(Meaning, on_delete=models.CASCADE)
class EntryForm(forms.ModelForm):
class Meta:
model = models.Entry
fields = ['title', 'slug']
MeaningFormSet = modelformset_factory(models.Meaning, fields=('title', 'language'))
class EntryUpdateView(UpdateView):
model = models.Entry
form_class = forms.EntryForm
formset_class = forms.MeaningFormSet
template_name = 'edit.html'
def get_context_data(self, **kwargs):
context = super(EntryUpdateView, self).get_context_data(**kwargs)
qs = models.Meaning.objects.filter(entry=self.get_object())
formset = forms.MeaningFormSet(queryset=qs)
context['meaning_formset'] = formset
return context
# edit.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_table }}
{{ meaning_formset.management_form }}
{% for meaning_form in meaning_formset %}
{{ meaning_form.as_p }}
<hr>
{% endfor %}
<input type="submit" value="Update"/>
</form>
答案 0 :(得分:2)
我解决了将post
方法添加到EntryUpdateView
类:
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
qs = models.Meaning.objects.filter(entry=self.get_object())
formsets = forms.MeaningFormSet(self.request.POST, queryset=qs)
if form.is_valid():
for fs in formsets:
if fs.is_valid():
fs.save()
return self.form_valid(form)
return self.form_invalid(form)