Django:在表单中显示中间表中的字段

2024-09-19 23:41:53 发布

您现在位置:Python中文网/ 问答频道 /正文

这方面的大多数问题似乎都集中在节省m2m表上。我很好奇如何以一种(或两种组合)形式查看中介表中的字段。在

我的想法是我有很多资源和食物。不同的食物可以有相同的资源,但数量不同。比方说:墨西哥煎饼有x磅的牛肉,但是法吉塔斯有y磅

我想创建一个表单来编辑玉米煎饼,这样我就可以看到/编辑/创建:餐点的名称、餐点中的资源以及与该餐点中的资源相关联的数量。我当前的代码显示一个表单,除了通过m2m表与资源相关联的金额外,还显示了一个表单

我有两个模型通过中间表连接:

class Resource(models.Model):
    name = models.CharField(max_length=200)
    unit = models.ForeignKey(Unit)
    units_per_pack = models.PositiveSmallIntegerField()
    packs_per_case = models.PositiveSmallIntegerField()
    allergens = models.ManyToManyField(Allergen, blank=True)

class Meal(models.Model):
    name = models.CharField(max_length=200)
    resources=models.ManyToManyField(Resource,through='MealResourceRelationship')
    recipe = models.TextField(default='')

class MealResourceRelationship(models.Model):
    resource = models.ForeignKey(Resource)
    meal = models.ForeignKey(Meal)
    units_per_person = models.DecimalField(max_digits=19,decimal_places=2)

我尝试使用一个简单的模型表单,如下所示:

^{2}$

从这个观点来看:

def meal_edit(request, pk=None, template_name='foodstuffs/meal_edit.html'):
    if id:
        meal = get_object_or_404(Meal, pk=pk)
    else:
        meal = Meal()
    if request.POST:
       form = MealForm(request.POST,instance=meal)
       if form.is_valid():
            meal_mod = form.save(commit=False)
            meal_mod.save()

            # remove existing resources                                                                                                                                                                      
            meal_mod.resources.clear()
            for resource in form.cleaned_data.get('resources'):
                meal_resource_rel = MealResourceRelationship(meal=meal_mod,
                                                             resource=resource,
                                                             units_per_person=1)
                meal_resource_rel.save()
            # messages.add_message(request, messages.SUCCESS, _('Meal correctly saved.'))                                                                                                                    
            # If the save was successful, redirect to another page                                                                                                                                           
            redirect_url = reverse('meal_list')
            return HttpResponseRedirect(redirect_url)
    else:
        form = MealForm(instance=meal)

    args = {}
    args.update(csrf(request))
    args['form'] = form
    args['meal'] = meal
    return render_to_response(template_name, args)

有什么想法吗?谢谢您!在


Tags: nameformmod表单modelsrequestsaveargs
1条回答
网友
1楼 · 发布于 2024-09-19 23:41:53

基于Django提供的解决方案(缺少完全定制的表单),我认为将这个问题分为两个部分是最简单的:

  1. 如何为与一顿饭相关的所有MealResourcesRelationship提供一个表单
  2. 如何在用餐表格旁边展示1号表格

第1个问题的答案在于Formsets,它允许一个表单的多个实例一起呈现。对于您的特定情况,您希望将这些实例绑定到父对象(一顿饭),您对Inline Formsets感兴趣,它允许您呈现由外键相关的表单的多个实例。 请参阅post以了解如何通过关系使用带m2m的内联表单集。在

对于第2部分),您只需要将原始表单和内联表单集呈现到同一页面。请参见post以获取示例。在

基于此,您可以按如下方式更新视图:

def meal_edit(request, pk=None, template_name='foodstuffs/meal_edit.html'):
    # ADDED: Created an inline formset factory for the meal resource relationship
    MealResourceFormset = forms.inlineformset_factory(Meal, Meal.resources.through, exclude=[])

    if id:
        meal = get_object_or_404(Meal, pk=pk)
    else:
        meal = Meal()

    if request.POST:
       form = MealForm(request.POST, instance=meal)
       if form.is_valid():
            meal_mod = form.save(commit=False)
            meal_mod.save()

            # remove existing resources                                                              
            meal_mod.resources.clear()
            for resource in form.cleaned_data.get('resources'):
                meal_resource_rel = MealResourceRelationship(meal=meal_mod,
                                                         resource=resource,
                                                         units_per_person=1)
                meal_resource_rel.save()
            # messages.add_message(request, messages.SUCCESS, _('Meal correctly saved.'))            
            # If the save was successful, redirect to another page                                   
            redirect_url = reverse('meal_list')
            return HttpResponseRedirect(redirect_url)
    else:
        # ADDED/EDITED: create both the meal form and resource formsets
        meal_form = MealForm(instance=meal)
        resource_formset = MealResourceFormset(instance=meal)                                                         

    args = {}
    args.update(csrf(request))
    args['form'] = meal_form
    # ADDED: pass through resource_formset to template
    args['formset'] = resource_formset
    args['meal'] = meal
    return render_to_response(template_name, args)

您还需要更新模板以呈现表单集,并更新MealForm以不呈现resources字段(因为您是通过formset呈现它的)。您可以通过编辑每个部分的表单来进一步自定义每个部分。在

希望这对你的项目有帮助,祝你好运!在

相关问题 更多 >