Подтвердить что ты не робот

Создание модели и связанных с ней моделей с помощью встроенных форм

[Я разместил это в Django users | Группы Google.]

Используя пример в встроенных документах форм, я могу редактировать объекты, принадлежащие определенной модели (используя modelforms). Я пытаюсь следовать той же схеме для создание новых объектов с использованием встроенных форм, но не удалось очистите мою голову, чтобы вывести рабочий вид для этой цели.

Используя тот же пример, что и в приведенной выше ссылке, как бы я пошел создание нового экземпляра модели "Автор" вместе со связанными с ней Объекты "Book"?

4b9b3361

Ответ 1

Сначала создайте модель модели автора.

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 %}

Ответ 2

Мне бы хотелось предложить небольшую настройку для решения 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" ).

Ответ 3

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 не является рекомендуемым методом, но он экономит немного логики и работает.

Изменить: Добавлена модель связи, переключенная на обычный внешний ключ вместо общего внешнего ключа, что приводит к путанице