Django ModelForm传递多个正在使用的ManytoMany?

时间:2014-01-13 19:50:03

标签: python django django-models django-forms django-templates

我试图弄清楚如何用Django(1.6)形式弄清楚两件事。我希望使用ModelForm创建一个表单,其模型具有多个使用的ManyToManyField。我似乎可以弄清楚如何在表单中显示ManyToMany项目。

我想弄清楚的另一件事是如何拆分表格。例如,如果我想要一个看起来像这样的表单。

注意:配方模型的一部分(名称,说明)然后是ManyToManyField(水果和随之而来的项目。)然后是配方模型(Fruit_notes)中的另一个项目,然后是第二个ManyToManyField ......等

表单示例:

姓名:__________________说明:___________


水果:___________数量:_________
水果笔记:____________


蔬菜:___________数量:__________
veg说明:___________


models.py文件

               from django.db import models


    class Vegetable(models.Model):
        name = models.CharField(max_length=150, blank=True)
        description = models.TextField(blank=True)

        def __unicode__(self):
            return self.name


    class Fruit(models.Model):
        name = models.CharField(max_length=150, blank=True)
        description = models.TextField(blank=True)

        def __unicode__(self):
            return self.name




    class Recipe(models.Model):
        name = models.CharField(max_length=450, blank=True)
        description = models.TextField(blank=True)
        fruits = models.ManyToManyField('Fruit', through='RecipeFruit')
        fruit_notes = models.TextField(blank=True)
        vegetables = models.ManyToManyField('Vegetable' through='RecipeVegetable')
        Vegetables_notes = models.TextField()


    class RecipeVegetable(models.Model):
        recipe = models.ForeignKey(Recipe)
        veg = models.ForeignKey(Vegetable)
        qty = models.FloatField()  


    class RecipeFruit(models.Model):
        recipe = models.ForeignKey(Recipe)
        fruit = models.ForeignKey(Fruit)
        qty = models.FloatField()

forms.py文件

    from django import forms
    from django.forms import ModelForm, Textarea
    from django.forms.formsets import formset_factory
    from models import Recipe, Vegetable, Fruit
    from crispy_forms.helper import FormHelper
    from crispy_forms.layout import Submit

    class CreateRecipeForm(forms.ModelForm):

        class Meta:
            model = Recipe


        def __init__(self, *args, **kwargs):
            super(CreateRecipeForm, self).__init__(*args, **kwargs)
            self.helper = FormHelper()
            self.helper.form_id = 'id-RecipeForm'
            self.helper.form_class = 'form-inline'
            self.helper.form_method = 'post'
            self.helper.form_action = 'submit_survey'

            self.helper.add_input(Submit('submit', 'Submit'))

我确实遇到过这个问题。 What are the steps to make a ModelForm work with a ManyToMany relationship with an intermediary model in Django?

看起来朝着解决这个问题迈出了一大步,但我很难掌握如何引入两件物品。 (例如,水果和蔬菜)

如果有人能指出我正确的方向,并提供一个小例子,那将非常感激。在查看django文档时,我真的没有看到任何拼写出来的东西。

1 个答案:

答案 0 :(得分:0)

前几天我和一对多关系工作,并且已经解决了这个问题(为了理解,我从我的源代码中修改了一些名称)。 我没有测试过你的例子,但它应该只需要很小的修改(如果需要),记住formset只能在ForeignKeys上工作,如果下面的波纹不起作用,请尝试使用model = Recipe.fruits.through或Recipe.vegetables.through 。 波纹管仅适用于一个内联formset,但您可以使用相同的方式添加其他formset:

    # forms.py

class RecipeForm(forms.ModelForm):
    ...
    class Meta:
        model = Recipe
        ....

class FruitForm(forms.ModelForm):
    ...
    class Meta:
        model = RecipeFruit
    ...


RecipeFormSet = inlineformset_factory(Recipe, RecipeFruit, form=FruitForm, extra=1)


# views.py

class RecipeCreateView(CreateView):
    form_class = RecipeForm
    template_name = "recipes/recipe_add.html"
    success_url = reverse_lazy('recipe-lists')

    def get(self, request, *args, **kwargs):
        """
        Handles GET requests and instantiates blank versions of the form
        and its inline formsets.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        recipe_formset = RecipeFormSet()
        return self.render_to_response(
            self.get_context_data(form=form,recipe_formset=recipe_formset))

    def post(self, request, *args, **kwargs):
        """
        Handles POST requests, instantiating a form instance and its inline
        formsets with the passed POST variables and then checking them for
        validity.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        recipe_formset = RecipeFormSet(request.POST)
        if (form.is_valid() and recipe_formset.is_valid()):
            return self.form_valid(form, recipe_formset)
        else:
            return self.form_invalid(form, recipe_formset)

    def form_valid(self, form, recipe_formset):
        """
        Called if all forms are valid. Creates a Recipe instance along with
        associated Ingredients and Instructions and then redirects to a
        success page.
        """
        self.object = form.save()
        recipe_formset.instance = self.object
        recipe_formset.save()
        return super(RecipeCreateView, self).form_valid(form)

    def form_invalid(self, form, recipe_formset):
        """
        Called if a form is invalid. Re-renders the context data with the
        data-filled forms and errors.
        """
        return self.render_to_response(
            self.get_context_data(form=form,recipe_formset=recipe_formset))