РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
408 of 818 menu

Функция inlineformset_factory

Функция inlineformset_factory применяется для создания формсета, который позволяет одновременно редактировать несколько объектов дочерней модели, связанных с одним родительским объектом через внешний ключ. Эта функция возвращает класс формсета, который наследуется от BaseInlineFormSet и предоставляет удобный интерфейс для работы с связанными данными. Основные параметры функции включают родительскую модель, дочернюю модель, количество дополнительных пустых форм и максимальное количество форм.

Синтаксис

from django.forms import inlineformset_factory InlineFormSet = inlineformset_factory( parent_model, model, form=ModelForm, formset=BaseInlineFormSet, fk_name=None, fields=None, exclude=None, extra=3, can_delete=True, can_order=False, max_num=None, min_num=None, validate_max=False, validate_min=False, absolute_max=None, can_delete_extra=True, renderer=None, widgets=None, localized_fields=None, labels=None, help_texts=None, error_messages=None, field_classes=None, factory_kwargs=None, )

Обязательными аргументами являются parent_model и model. Все остальные параметры опциональны и позволяют гибко настраивать поведение формсета.

Пример

Рассмотрим простой пример работы с inlineformset_factory. У нас есть модели Author и Book, где книга связана с автором через внешний ключ. Создадим формсет для редактирования книг конкретного автора:

from django.db import models from django.forms import inlineformset_factory from myapp.models import Author, Book # Модели class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=200) author = models.ForeignKey(Author, on_delete=models.CASCADE) # Создаём формсет для модели Book с привязкой к Author BookFormSet = inlineformset_factory( Author, Book, fields=['title'], extra=2, can_delete=True ) # Получаем автора из базы данных author = Author.objects.get(pk=1) # Создаём формсет с данными существующего автора formset = BookFormSet(instance=author) # Выводим количество форм в формсете print(f"Number of forms: {len(formset)}")

Результат выполнения кода:

"Number of forms: 3"

В результате мы получили формсет, который содержит две дополнительные пустые формы для добавления новых книг и одну форму для существующей книги автора. Всего три формы.

Пример

Теперь рассмотрим, как обрабатывать данные, переданные методом POST, в представлении. Используем те же модели и формсет для сохранения изменённых данных:

from django.shortcuts import render, redirect from django.forms import inlineformset_factory from myapp.models import Author, Book def edit_author_books(request, author_id): author = Author.objects.get(pk=author_id) BookFormSet = inlineformset_factory( Author, Book, fields=['title'], extra=2, can_delete=True ) if request.method == 'POST': formset = BookFormSet(request.POST, instance=author) if formset.is_valid(): formset.save() return redirect('author_detail', author_id=author.id) else: formset = BookFormSet(instance=author) return render(request, 'edit_books.html', {'formset': formset})

В этом примере при GET-запросе мы создаём формсет с данными автора. При POST-запросе передаём данные в формсет, проверяем их валидность и сохраняем. Метод save формсета автоматически обработает создание, обновление и удаление связанных объектов в зависимости от переданных данных.

Пример

Функция inlineformset_factory позволяет указать, какие поля дочерней модели должны отображаться в формах. Рассмотрим случай, когда нужно исключить некоторые поля или использовать кастомную форму:

from django import forms from django.forms import inlineformset_factory from myapp.models import Author, Book # Кастомная форма для книги class BookForm(forms.ModelForm): class Meta: model = Book fields = ['title', 'publication_year'] def clean_title(self): title = self.cleaned_data.get('title') if len(title) < 3: raise forms.ValidationError("Title is too short!") return title # Создаём формсет с кастомной формой BookFormSet = inlineformset_factory( Author, Book, form=BookForm, extra=1, can_delete=False, max_num=5 ) author = Author.objects.get(pk=1) formset = BookFormSet(instance=author) # Получаем словари с данными форм for form in formset: print(form.cleaned_data if form.is_valid() else "Invalid form")

Результат выполнения кода для валидных форм:

"{'title': 'Django for Beginners', 'publication_year': 2023}" "{'title': 'Advanced Django', 'publication_year': 2024}" "{'title': '', 'publication_year': None}"

В этом примере мы использовали кастомную форму с валидацией поля title и установили ограничение на максимальное количество форм до пяти. Параметр can_delete отключён, поэтому удаление записей через формсет недоступно.

Смотрите также

  • функция modelformset_factory,
    которая создаёт формсет для модели без привязки к родительскому объекту
  • функция formset_factory,
    которая создаёт формсет из обычных форм Django
  • класс save,
    который сохраняет данные формы модели в базу данных
  • атрибут instance,
    который связывает форму с конкретным объектом модели
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить