представления на основе классов django со встроенной моделью-формой или набором форм
у меня есть следующие модели:
class Bill(models.Model):
date = models.DateTimeField(_("Date of bill"),null=True,blank=True)
class Item(models.Model):
name = models.CharField(_("Name"),max_length=100)
price = models.FloatField(_("Price"))
quantity = models.IntegerField(_("Quantity"))
bill = models.ForeignKey("Bill",verbose_name=_("Bill"),
related_name="billitem")
Я знаю, что это возможно:
from django.forms.models import inlineformset_factory
inlineformset_factory(Bill, Item)
а затем обработать это через стандартный вид.
теперь мне было интересно, есть ли способ добиться того же (что и в строке для добавления/редактирования элементов, принадлежащих законопроекту) с помощью представления на основе классов (не для админ-интерфейса).
7 ответов:
ключевые моменты это:
созданный
FormSet
s внутриforms.py
используяinlineformset_factory
:BookImageFormSet = inlineformset_factory(BookForm, BookImage, extra=2) BookPageFormSet = inlineformset_factory(BookForm, BookPage, extra=5)
вернул
FormSet
s в пределах aCreateView
классviews.py
:def get_context_data(self, **kwargs): context = super(BookCreateView, self).get_context_data(**kwargs) if self.request.POST: context['bookimage_form'] = BookImageFormSet(self.request.POST) context['bookpage_form'] = BookPageFormSet(self.request.POST) else: context['bookimage_form'] = BookImageFormSet() context['bookpage_form'] = BookPageFormSet() return context
используется
form_valid
чтобы сохранить форму и набор форм:def form_valid(self, form): context = self.get_context_data() bookimage_form = context['bookimage_formset'] bookpage_form = context['bookpage_formset'] if bookimage_form.is_valid() and bookpage_form.is_valid(): self.object = form.save() bookimage_form.instance = self.object bookimage_form.save() bookpage_form.instance = self.object bookpage_form.save() return HttpResponseRedirect('thanks/') else: return self.render_to_response(self.get_context_data(form=form))
Я просто добавил свою собственную версию после проверки некоторых из этих готовых CBV. Мне особенно нужен был контроль над
multiple formsets -> one parent
в одном представлении каждый с отдельными функциями сохранения.Я в основном запихнул привязку данных набора форм в
get_named_formsets
функция, которая вызываетсяget_context_data
иform_valid
.там я проверяю, все ли наборы форм действительны, а также ищу метод, который переопределяет простой старый
formset.save()
на основе каждого набора форм для пользовательского сохранения.в шаблон отображает наборы форм через
{% with named_formsets.my_specific_formset as formset %} {{ formset }} {{ formset.management_form }} {% endwith %}
Я думаю, что буду использовать эту систему регулярно.
class MyView(UpdateView): # FormView, CreateView, etc def get_context_data(self, **kwargs): ctx = super(MyView, self).get_context_data(**kwargs) ctx['named_formsets'] = self.get_named_formsets() return ctx def get_named_formsets(self): return { 'followup': FollowUpFormSet(self.request.POST or None, prefix='followup'), 'action': ActionFormSet(self.request.POST or None, prefix='action'), } def form_valid(self, form): named_formsets = self.get_named_formsets() if not all((x.is_valid() for x in named_formsets.values())): return self.render_to_response(self.get_context_data(form=form)) self.object = form.save() # for every formset, attempt to find a specific formset save function # otherwise, just save. for name, formset in named_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 http.HttpResponseRedirect('') def formset_followup_valid(self, formset): """ Hook for custom formset saving.. useful if you have multiple formsets """ followups = formset.save(commit=False) # self.save_formset(formset, contact) for followup in followups: followup.who = self.request.user followup.contact = self.object followup.save()
вы должны попробовать django-extra-views. Ищите
CreateWithInlinesView
иUpdateWithInlinesView
.
Я красный общий исходный код 1.3-beta-1:
код абсолютно не готов для редактирования списка или здесь есть какая-то черная магия. Но я думаю, что это может быть реализовано быстро.
Если вы посмотрите на Джанго.вид.родовой.edit (который поддерживает подробное редактирование объектов) модуль, как он использует django.вид.родовой.модуль детализации.
Я думаю, что Джанго.вид.родовой.модуль list_edit может быть реализован с помощью django.вид.родовой.список и некоторые часть из Джанго.вид.родовой.редактировать.
Я внес некоторые изменения в исходное решение, чтобы позволить formset. is_valid () работать:
if self.request.POST: context['fs'] = MyInlineFS(self.request.POST, instance=self.object) else: context['fs'] = MyInlineFS(instance=self.object)
код в ответе Джордана не сработал для меня. Я написал У меня вопрос об этом, который я считаю, что теперь я решил. Первым аргументом для inlineformset_factory должна быть Book,не Книжная форма.
мне нужно было внести еще одну модификацию в представление Джордана и Спика
get_context_data()
для того чтобыformset.non_form_errors
существуют в контексте шаблона.... if self.request.POST: context['fs'] = MyInlineFS(self.request.POST, instance=self.object) context['fs'].full_clean() # <-- new else: context['fs'] = MyInlineFS(instance=self.object) return context
Comments