[Я разместил это в Django users | Группы Google.]
Используя тот же пример, что и в приведенной выше ссылке, как бы я пошел создание нового экземпляра модели "Автор" вместе со связанными с ней Объекты "Book"?
[Я разместил это в Django users | Группы Google.]
Используя тот же пример, что и в приведенной выше ссылке, как бы я пошел создание нового экземпляра модели "Автор" вместе со связанными с ней Объекты "Book"?
Сначала создайте модель модели автора.
author_form = AuthorModelForm()
затем создайте объект-фиктивный автор:
author = Author()
Затем создайте встроенный набор форм, используя этот фиктивный автор:
formset = BookFormSet(instance=author) #since author is empty, this formset will just be empty forms
Отправьте это в шаблон. После возвращения данных обратно в представление вы создадите Author:
author = AuthorModelForm(request.POST)
created_author = author.save() # in practice make sure it valid first
Теперь подключите встроенный набор форм вместе с созданным автором и затем сохраните:
formset = BookFormSet(request.POST, instance=created_author)
formset.save() #again, make sure it valid first
изменить:
Чтобы не иметь флажков в новых формах, сделайте это шаблон:
{% for form in formset.forms %}
<table>
{% for field in form %}
<tr><th>{{field.label_tag}}</th><td>{{field}}{{field.errors}}</td></tr>
{% endfor %}
{% if form.pk %} {# empty forms do not have a pk #}
<tr><th>Delete?</th><td>{{field.DELETE}}</td></tr>
{% endif %}
</table>
{% endfor %}
Мне бы хотелось предложить небольшую настройку для решения nbv4:
Предположим, что вы не создаете пустой created_author вне инструкции if-else и, следовательно, должны вставлять набор форм внутри author_form.is_valid(), чтобы избежать ошибок времени выполнения, когда author_form недействительна (и, следовательно, no created_author не является экземпляр).
Вместо:
if request.method == 'POST':
author_form = AuthorModelForm(request.POST)
if author_form.is_valid():
created_author = author_form.save()
formset = BookFormSet(request.POST, instance=created_author)
if formset.is_valid():
formset.save()
return HttpResponseRedirect(...)
else:
...
Выполните следующие действия:
if request.method == 'POST':
author_form = AuthorModelForm(request.POST)
if author_form.is_valid():
created_author = author_form.save(commit=False)
formset = BookFormSet(request.POST, instance=created_author)
if formset.is_valid():
created_author.save()
formset.save()
return HttpResponseRedirect(...)
else:
...
Эта версия позволяет избежать создания created_author до тех пор, пока у book_formset не будет возможности проверить. Вариант использования для исправления заключается в том, что кто-то заполняет действующий AuthorForm с недопустимым BookFormSet и сохраняет повторную отправку, создавая несколько записей авторов без связанных с ними книг. Это похоже на мое приложение для отслеживания проектов (замените "Author" на "Project" и "Book" на "Role" ).
models.py (контакт)
class Contact(models.Model)
first = models.CharField(max_length=30)
middle = models.CharField('M.I.',max_length=30, blank=True)
last = models.CharField(max_length=30)
sort_order = models.PositiveIntegerField(default=99)
models.py (ссылка)
class Link(models.Model):
contact = models.ForeignKey(Contact)
link = models.URLField()
description = models.CharField(max_length=30)
access_date = models.DateField(blank=True,null=True)
forms.py
from django.forms import ModelForm
from contacts.models import Contact
class ContactAjaxForm(ModelForm):
class Meta:
model=Contact
views.py
def edit(request,object_id=False):
LinkFormSet = inlineformset_factory(Contact, Link, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f=forms.ContactAjaxForm(request.POST, request.FILES, instance=contact)
fs = LinkFormSet(request.POST,instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = forms.ContactAjaxForm(instance=contact)
fs = LinkFormSet(instance=contact)
return render_to_response(
'contacts/edit.html',
{'fs': fs, 'f': f, 'contact': contact}
)
Это не основано на примере в книге, оно отредактировано из некоторого кода на моем сайте. Я не проверял это, поэтому могут быть некоторые ошибки, но в целом это должно быть твердым. Использование пустого экземпляра Contact не является рекомендуемым методом, но он экономит немного логики и работает.
Изменить: Добавлена модель связи, переключенная на обычный внешний ключ вместо общего внешнего ключа, что приводит к путанице