Django formset_factory против modelformset_factory против inlineformset_factory

Формы могут быть сложными в Django. Наборы форм могут вызвать у вас желание выйти из Django. Я в этот момент.

Каковы различные варианты использования и соображения о том, какой из них использовать?

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

Ниже приведен некоторый псевдокод с предположениями/ограничениями, который поможет вам понять различия. Это может помочь предоставить псевдокод, например, какая форма (ModelForm или обычная) идет с набором форм или что должно быть popped из формы, учитывая, что это похоже на тенденцию создания форм с отношениями.

Предполагая, что у вас есть несколько моделей:

class Dish(models.Model):
    name = models.CharField(max_length=50)


class Meal(models.Model):
    name = models.CharField(max_length=50)
    dishes = models.ManyToManyField(Dish,
                                    # through='OPTIIONALMealDishIntermediaryClassTable',
                                    related_name="meal")

class Reservation(models.Model):
    date = models.DateTimeField()
    greeting = models.CharField(max_length=255)
    meal = models.OneToOneField(Meal, on_delete=models.CASCADE)


class MealPhotos(models.Model):
    photo = models.OneToOneField(Photo, on_delete=models.CASCADE, related_name='mealPhoto')
    meal = models.ForeignKey(Meal, on_delete=models.CASCADE)
    # optional, so a photo can be attached to a dish if the picture is just of the dish
    dish = models.ForeignKey(Dish, blank=True, null=True, on_delete=models.CASCADE)

И вы хотите создать новый Meal, вы хотите отправить Reservation одновременно:

  • какой завод вы бы использовали?
  • это зависит от того, все ли формы ModelForms? (имеется в виду, как бы вы справились с назначением Meal его Reservation)
  • assuming:
    • at this stage you know which Meal it is, but you still have to make a Reservation at the same time/same view.
    • вы не знаете, какие Dishes вы собираетесь готовить, так как бронирование скажет вам.
    • MealPhotos еще не будет, так как еда еще не приготовлена.
    • Вы хотите создать еду и бронирование на одной и той же форме/экране

Позже вы захотите добавить несколько блюд, основываясь на том, что говорит Reservation:

  • какой завод вы бы использовали?
  • это зависит от того, все ли формы ModelForms?
  • assuming:
    • at this stage you know which Meal it is, and you have a Reservation
    • вы собираетесь назначить блюда еде на основе Reservation, и у вас достаточно информации для этого, и вы можете легко использовать ModelForm, но не обязательно

Позже человек, который ест блюдо, хочет сделать несколько фотографий, и вы не знаете, сколько он сделает.

  • какой завод вы бы использовали?
  • это зависит от того, все ли формы ModelForms?
  • assuming:
    • we will require them to take at least two
    • у нас есть доступ к Meal, Reservation и Dishes
    • фотография может быть дополнительно назначена Dish

person chris Frisina    schedule 28.10.2018    source источник
comment
Я тоже в том же духе, что и с формами. Кажется, что они были созданы с учетом довольно специфического использования, и если вам нужно что-то другое, становится адом, чтобы все части хорошо работали вместе. Жду ответа и здесь   -  person vladimir.gorea    schedule 26.02.2019


Ответы (1)


Разница между тремя фабриками форм в основном:

  • formset_factory позволяет отображать множество форм вместе, но эти формы НЕ обязательно связаны с конкретной моделью базы данных (это не то, что вам нужно, так как у вас есть модели для всего). )
  • modelformset_factory позволяет создавать/редактировать несколько объектов модели Django вместе, например, если вы управляете меню, вы можете использовать modelformset_factory(Dish, fields=('name'))
  • inlineformset_factory позволяет управлять набором объектов модели Django, связанных с одним экземпляром другой модели. Например, если вы хотите управлять всеми фотографиями еды, сделанными во время определенного приема пищи, это то, что вы должны использовать

Чтобы ответить на ваши конкретные сценарии:

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

Позже, если вы захотите прикрепить несколько Блюд к Блюду, вы должны использовать inlineformset_factory(Meal, Dish) для редактирования нескольких Блюд, принадлежащих к одному Блюду.

Поскольку мы используем inlineformset_factory, мы должны создать экземпляр Meal в представлении, которое отображает форму. Что-то вроде этого:

DishFormSet = inlineformset_factory(Meal, Dish)
bday_dinner = Meal.objects.create(name='30th Birthday dinner')
formset = DishFormSet(instance=bday_dinner)

Для тех, кто загружает фотографии еды, вы должны использовать:

PhotosFormSet = inlineformset_factory(Meal, MealPhotos)
bday_dinner = Meal.objects.get(name='30th Birthday dinner')
formset = PhotosFormSet(instance=bday_dinner)

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

Примечание. В первом сценарии я не проверял, поддерживается ли фабрикой форм использование ManyToManyField в качестве Meal.dishes. Если это не так, вы можете просто использовать ModelFormset(Dish) и после их создания связать их с едой в представлении Django, которое обрабатывает отправку формы.

person Lushen Wu    schedule 10.11.2019
comment
Это наиболее ясное описание трех фабрик наборов форм, которые я когда-либо видел. Спасибо. Но не могли бы вы добавить вариант использования formset_factory. Не совсем очевидно, зачем вы вообще это используете и что он предлагает. - person Bernd Wechner; 25.01.2021
comment
@BerndWechner использовать его или нет, это выбор пользователя, и причина его существования заключается в том, чтобы построить два других (modelformset_factory и inlineformset_factory) поверх предоставляемой им абстракции. Я видел менее опытных разработчиков django, которые не могли понять последнего, использовали базовую форму formset_factory и усложняли себе жизнь. - person Maziyar Mk; 13.06.2021
comment
Конечно, это, очевидно, выбор пользователя. Но чтобы сделать осознанный выбор, вариант использования formset_factory был бы очень полезен. - person Bernd Wechner; 22.06.2021