Django formset_factory vs modelformset_factory vs inlineformset_factory

标签 django django-forms formset inline-formset

Django 中的表单可能很复杂。 Formsets 会让你想退出 Django。我就在那个时候。

有哪些不同的用例以及使用哪个(哪些)用例的注意事项?

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

下面是一些带有假设/限制的伪代码,以帮助您帮助我理解差异。提供伪代码可能会有所帮助,例如Formset 搭配什么样的Form(ModelForm 或regular),或者应该是什么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)

而你想创建一个新的 Meal ,您要发送 Reservation同时:
  • 你会用哪个工厂?
  • 是否取决于表格是否都是ModelForms ? (意味着您将如何处理分配 MealReservation )
  • 假设:
  • 在这个阶段你知道哪个Meal是的,但你仍然需要做一个 Reservation同时/相同的观点。
  • 你不知道哪个Dish你会做饭,因为预订会告诉你。
  • MealPhotos不会存在,因为这顿饭还没有准备好。
  • 您想在同一个表单/屏幕上创建餐点和预订

  • 后来想加点菜,根据什么Reservation说:
  • 你会用哪个工厂?
  • 是否取决于表格是否都是ModelForms ?
  • 假设:
  • 在这个阶段你知道哪个Meal是的,你有一个 Reservation
  • 您将根据 Reservation 为餐点分配菜肴,并且您有足够的信息可以这样做,并且可以轻松使用 ModelForm,但不是必需的

  • 后来吃这道菜的人想拍一些照片,你不知道他们会拍多少
  • 你会用哪个工厂?
  • 是否取决于表格是否都是ModelForms ?
  • 假设:
  • 我们将要求他们至少带两个
  • 我们可以访问 Meal , Reservation , 和 Dishes
  • 可以选择将照片分配给 Dish
  • 最佳答案

    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)编辑属于单餐的多道菜
    由于我们使用的是 inlineformset_factory ,我们必须在呈现表单的 View 中创建 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 View 中的 Meal。

    关于Django formset_factory vs modelformset_factory vs inlineformset_factory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53035151/

    相关文章:

    python - Django ModelFormSet 单击 "Submit"保存表单但不更新到数据库

    python - 在 django 请求之间共享单个连接

    python - 使用 django、virtualenv、gunicorn 和 nginx 设置服务器以托管多个域

    python - Django ModelForm 不允许必填字段为空值?

    python - 切换祖先顺序会破坏初始化吗?

    python - Django formset UpdateView 不允许我上传文件

    python - 允许逐跳 header Django

    javascript - 如何使用angularJS在成功提交后刷新页面

    python - 在 Django 表单集上迭代时显示附加数据

    Django 表单集无效——为什么不呢?