Django ModelMultipleChoiceField用于另一个模型的多对多

时间:2013-05-02 01:36:19

标签: django django-models django-forms

我正在开发一个DIY应用程序(Django 1.5),我遇到了障碍。涉及的主要模型是GuideToolItemStep。指南可以包含许多工具和项目,工具或项目可以属于许多指南。步骤也是如此 - 它可以有许多工具和项目,工具或项目可以属于许多步骤。指南有很多步骤,步骤属于指南。

指南多对多项目

指南多对多工具

指南一对多步骤

步骤多对多

步骤多对多工具

路障......

在指南级别,我希望工具和项目选项是无限的。但是在步骤级别,我希望工具和项目选项仅限于分配给它所属的指南的选项。基本上,在创建/编辑步骤时,我想列出通过指南提供的所有工具和项目的复选框。用户选择当前步骤所需的那些。每个步骤都有不同的工具和项目组合(因此需要复选框)。

我发现了Step的ModelForm类的ModelMultipleChoiceField。在那里,我可以指定一个查询集。 但是,如何获取对Guide模型实例的访问权以检索其工具和项目,以便我可以正确构建选择? 我想提供类似于你会在视图中做什么...

Guide.objects.get(pk=n).tools.all()
Guide.objects.get(pk=n).items.all()

如何通过ModelMultipleChoiceField实现这一目标?我希望我能够清楚地解释这一点。

提前感谢您的帮助。

class Tool(models.Model):
    name = models.CharField(max_length=100)
    ...


class Item(models.Model):
    name = models.CharField(max_length=100)
    ...


class Guide(models.Model):
    models.CharField(max_length=100)
    description = models.CharField(max_length=500)
    tools = models.ManyToManyField(Tool, null=True, blank=True)
    items = models.ManyToManyField(Item, null=True, blank=True)
    ...


class Step(models.Model):
    title = models.CharField(max_length=100)
    body = models.TextField()
    guide = models.ForeignKey(Guide)
    tools = models.ManyToManyField(Tool, null=True, blank=True)
    items = models.ManyToManyField(Item, null=True, blank=True)

编辑:5/2 进一步阅读后,看起来我必须覆盖__init__的{​​{1}}方法,在那里我获得对ModelMultipleChoiceField的引用,允许我创建我的查询,self.instanceself.instance.guide.tools.all()。然后通过self.instance.guide.items.all()创建字段。

我现在在工作,所以直到今晚晚些时候才能尝试这个。我会报告我的调查结果。

1 个答案:

答案 0 :(得分:0)

我最终做的是以下内容。我在ModelForm类中定义了一个用于创建ModelMultipleChoiceField的方法。原因是在请求创建步骤页面时,没有与步骤关联的指南,直到您保存(POST ...假设验证成功)。但我确实可以访问指南中将创建Step的slug字段。我从URL获得。 slug字段在我的应用程序中是独一无二的。所以我通过我创建的新方法将slug从我的视图传递给表单。从那里,我可以获得分配给指南的工具,并在我的模板中在表单上提供这些选项。

<强> forms.py

class NewStepForm(forms.ModelForm):
    ...
    def create_tools_field(self, slug):
        self.fields['tools'] = forms.ModelMultipleChoiceField(
            queryset=Guide.objects.get(slug=slug).tools.all(),
            widget=forms.CheckboxSelectMultiple(attrs={'class': 'unstyled'})
        )
    ...

<强> views.py

class NewStepView(View):

    form_class = NewStepForm
    initial = {'key': 'value'}
    template_name = "guides/guide_step_new.html"

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(NewStepView, self).dispatch(*args, **kwargs)

    def get(self, request, *args, **kwargs):
        slug = kwargs.get('slug')
        form = self.form_class(initial=self.initial)
        form.create_tools_field(slug)
        return render(request,  self.template_name, {'form': form})