【发布时间】:2014-09-06 12:34:41
【问题描述】:
我正在尝试使用内联表单集创建基于类的表单视图。我想要一个“添加”按钮,它将向表单集添加一个新行,并且我希望它可以在没有 javascript 的情况下工作。
我找到了一些有用的网站,这些网站让我可以创建一些粗略的代码(如下)。
https://stackoverflow.com/a/11910420/3800244:提供了一种优雅/干燥的方法来将表单集添加到 CBV。
http://pytipz.blogspot.com.au/2012/09/django-adding-inline-formset-rows.html:展示了如何在视图中向表单集添加行,但它似乎是针对基于函数的视图。
我的用例是一个纸牌游戏网站。我有一张牌桌、一张牌桌和一张牌桌。卡片表充满了数据,当人们创建卡片组时,他们需要能够为该卡片组选择卡片(都在同一页面/表单上)。这是我到目前为止的一些粗略代码;
models.py
class Card(models.Model):
title = models.CharField()
class Deck(models.Model):
title = models.CharField()
class CardsInDeck(models.Model):
deck = models.ForeignKey(Deck)
card = models.ForeignKey(Card)
quantity = models.PositiveSmallIntegerField(blank=False, default=1)
forms.py
class DeckForm(forms.ModelForm):
class Meta:
model = Deck
CardsInDeckFormSet = inlineformset_factory(Deck, CardsInDeck, extra=1)
views.py
class Deck_FormView(generic.edit.FormView):
template_name = 'create_deck.html'
model = Deck
form_class = DeckForm
success_url = 'viewdeck' #just an example
def get_formsets(self):
return {
'cards': CardsInDeckFormSet(self.request.POST or None, prefix='cards'),
}
def get_context_data(self, **kwargs):
context = super(Deck_FormView, self).get_context_data(**kwargs)
context['formsets'] = self.get_formsets()
return context
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
if 'add_card' in request.POST:
request.POST = request.POST.copy()
request.POST['cards-TOTAL_FORMS'] = int(request.POST['cards-TOTAL_FORMS']) + 1
return self.render_to_response(self.get_context_data(form=form))
formsets = self.get_formsets()
if (form.is_valid() and all((f.is_valid() for f in formsets.values()))):
return self.form_valid(form, formsets)
else:
return self.form_invalid(form)
def form_valid(self, form, formsets):
self.object = form.save()
for name, formset in formsets.items():
formset_save_func = getattr(self, 'formset_{0}_valid'.format(name), None)
if formset_save_func is not None:
formset_save_func(formset)
else:
formset.save()
return HttpResponseRedirect(self.get_success_url())
def formset_cards_valid(self, formset):
cards_formsets = formset.save(commit=False)
for i in cards_formsets:
i.deck = self.object
i.save()
create_deck.html
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<fieldset>
<legend>Cards in deck</legend>
{{ formsets.cards.management_form }}
{% for form in formsets.cards %}
{{ form.id }}
<div class="inline {{ formsets.cards.prefix }}">
{{ form }}
</div>
{% endfor %}
<input type='submit' name='add_card' value="Add another card" />
</fieldset>
<br>
<input type='hidden' name='action' value="deck">
<input type='submit' name='submit' value="Save Deck" />
</form>
所以我的代码使用了我最初引用的方法。它显示表单和表单集,单击“添加”按钮会重新加载带有额外表单集行的页面。保存也可以。
问题是;创建新行时没有任何“默认值”(即在卡选择输入中未选择任何内容,并且未在数字输入中输入默认数量 1)。此外,新的“空”行通过验证,HTML 呈现“此字段是必需的”。每个字段的错误。
我想解决这些问题,使其对用户更实用。我不知道该怎么做。我想知道它是否与将 is_bound 设置为表单/表单集有关?我也相信以下链接可能是相关的,但我不知道如何实现它(如果确实是解决方案):Django class based views and formsets
【问题讨论】:
标签: django django-forms django-views django-class-based-views