Django中的表单可能很复杂。表单集会让你想要退出Django。我已经到了那个地步。
使用哪一个用例有哪些不同的用例和注意事项?
我正在寻找一些关于何时使用每个工厂的更好指导,因为它们似乎取决于你何时知道什么类型的表单、字段,以及你是否在创建、编辑或删除(完全是单个表单还是父模型(。我读了很多演练,但很难看到更大的画面,尤其是当我试图从基于函数的视图转移到基于类的视图时。
以下是一些带有假设/限制的伪代码,可以帮助您理解其中的差异。提供伪代码可能会有所帮助,例如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
?(意思是您将如何处理将Meal
分配给Reservation
( - 假设:
- 在这个阶段,您知道它是哪个
Meal
,但您仍然必须在同一时间/同一视图中生成Reservation
- 你不知道你要做哪个
Dish
,因为预订会告诉你的 MealPhotos
还不存在,因为这顿饭还没做好- 您希望在同一表单/屏幕上创建餐点和预订
- 在这个阶段,您知道它是哪个
然后,你想根据Reservation
的内容添加一些菜肴:
- 您会使用哪家工厂
- 这取决于表格是否都是
ModelForms
- 假设:
- 在这个阶段,您知道它是哪个
Meal
,并且您有一个Reservation
- 您将根据
Reservation
为膳食分配菜肴,并且您有足够的信息可以这样做,并且可以很容易地使用ModelForm,但不是必需的
- 在这个阶段,您知道它是哪个
后来,吃这道菜的人想拍一些照片,你不知道他们会拍多少
- 您会使用哪家工厂
- 这取决于表格是否都是
ModelForms
吗 - 假设:
- 我们将要求他们至少服用两次
- 我们可以访问
Meal
、Reservation
和Dishes
- 可以选择将照片分配给
Dish
三个表单集工厂之间的差异基本上是:
- formset_factory允许您一起呈现一堆表单,但这些表单不一定与特定的数据库模型相关(这不是您所需要的,因为您有适用于所有内容的模型(
-
modelformset_factory允许您一起创建/编辑一堆Django模型对象,例如,如果您正在管理;菜单";你可以用
modelformset_factory(Dish, fields=('name'))
- inlineformset_factory允许您管理一堆Django模型对象,这些对象都与另一个模型的单个实例相关。例如,如果你想管理在特定用餐时拍摄的所有用餐照片,这就是你要使用的
要回答您的特定场景:
如果你想要一个同时创建一顿饭和一个预订的页面,而不分配任何菜肴,你不需要任何表格集。您可以使用用餐模式表和预订模式表。
稍后,如果您想将多个菜附加到餐中,您可以使用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,所有提交的照片都与同一份套餐相关联,但允许将每张照片分配给不同的套餐(通过表格中的下拉菜单(。
注意:在第一个场景中,我还没有测试formset工厂是否支持使用ManyToManyField作为Meal.dishes。如果不是,那么您可以简单地使用ModelFormset(Dish)
,在创建它们之后,将它们链接到Django视图中处理表单提交的Meal。