Django formset_factory vs模型formset_factory vs inlineformset_factory

chr*_*ina 11 django django-forms formset inline-formset

在Django中,表单可能很复杂。表单集可以使您想退出Django。我在那个时候。

有哪些不同的用例,以及要使用哪些用例的注意事项?

我正在寻找有关何时使用每个工厂的更好的指导,因为它们似乎取决于您何时知道什么类型的表单,字段以及是否要创建,编辑或删除(单个表单完全或单独)。父模型)。我已经阅读了许多演练,但是正在努力查看大图,尤其是当我尝试从基于函数的视图转换为基于类的视图时。

以下是一些带有假设/限制的伪代码,可帮助您帮助我理解不同之处。提供伪代码可能会有所帮助,例如哪种类型的表单(ModelForm或常规)与Formset一起使用,或者应该pop从表单中获取什么,因为这似乎是创建具有关系的表单的趋势。

假设您有一些模型:

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)
Run Code Online (Sandbox Code Playgroud)

您想创建一个new Meal,同时要发送一个Reservation

  • 您将使用哪个工厂?
  • 是否取决于表格是否全部ModelForms?(这意味着你将如何手柄assignming了MealReservation
  • 假设:
    • 在这个阶段您知道Meal它是什么,但是您仍然必须Reservation同时进行一次/相同的视图。
    • 您不知道Dish要烹饪哪种食物,因为预订会告诉您。
    • MealPhotos 由于餐尚未准备好,因此将不存在。
    • 您要在同一表格/屏幕上创建餐点和预订

然后,您要根据提示添加一些菜肴Reservation

  • 您将使用哪个工厂?
  • 是否取决于表格是否全部ModelForms
  • 假设:
    • 在这个阶段,您知道Meal它是什么,并且您有一个Reservation
    • 您将基于来为餐点分配餐点Reservation,并且您有足够的信息来这样做,并且可以轻松使用ModelForm,但不是必需的

后来,吃菜的人想拍照,而你不知道要拍几张。

  • 您将使用哪个工厂?
  • 是否取决于表格是否全部ModelForms
  • 假设:
    • 我们将要求他们至少服用两个
    • 我们有机会获得MealReservationDishes
    • 可以选择将照片分配给 Dish

Lus*_* Wu 21

3个formset工厂的区别基本上是:

  • formset_factory允许您呈现一堆表格在一起,但这些形式必然与特定数据库模型(这是不是你所需要的,因为你的一切型号)
  • modelformset_factory允许您一起创建/编辑一堆 Django 模型对象,例如,如果您正在管理“菜单”,您可以使用modelformset_factory(Dish, fields=('name'))
  • inlineformset_factory允许您管理一堆与另一个模型的单个实例相关的 Django 模型对象。例如,如果您想管理在特定膳食中拍摄的所有膳食照片,这就是您将使用的

要回答您的具体情况:

如果您想要一个页面同时创建一个 Meal 和一个 Reservation,而不分配任何 Dishes,则不需要任何表单集。您可以只使用 ModelForm for Meal 和 ModelForm for Reservation。

稍后,如果您想将多个 Dishes 附加到 Meal,您可以使用inlineformset_factory(Meal, Dish)来编辑属于一个 Meal 的多个 Dishes

由于我们使用的是inlineformset_factory,我们必须在呈现表单的视图中创建 Meal 实例。像这样的东西:

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

对于上传膳食照片的人,您可以使用:

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

这告诉 Django 所有提交的照片都与那顿饭相关联,但允许将每张照片分配到不同的盘子(通过表单中的下拉菜单)。

注意:在第一个场景中,我还没有测试过表单集工厂是否支持使用 ManyToManyField 作为 Meal.dishes。如果不是,那么您可以简单地使用 aModelFormset(Dish)并在创建这些之后,将它们链接到处理表单提交的 Django 视图中的 Meal。