如何为多对多案例将多个选择字段更改为多个输入字段?

时间:2010-09-01 17:27:07

标签: django django-forms django-models

当我显示ToolBoxEditForm时,它使用多个选择字段。 但我想要的是一个表单,让用户可以将工具箱中的每个工具编辑为文本字段。我无法弄清楚如何用多对多字段来做这件事。

class Tool(models.Model):
    tool_name = models.CharField(unique=True, max_length=200)
......

class ToolBox(models.Model):
    tools = models.ManyToManyField(Tool,max_length=300)

class ToolBoxEditForm (ModelForm):
    tools = ???
    class Meta:
      model = ToolBox
      exclude  = ('user', 'popularity',)

2 个答案:

答案 0 :(得分:2)

最性感的解决方案

您可以使用此处描述的jquery自动完成工具之一:Facebook style JQuery autocomplete plugin

然后是以下形式:

class ToolBoxEditForm (ModelForm):
    tools = forms.CharField(widget=forms.Textarea, required=False)

    def clean_tools(self):
        tool_data = self.cleaned_data.get('tools',None)
        tools = []
        #here, a comma is used a delim, so it's not allowed in the tool name.
        for td in tool_data.split(','): 
            t, _ = Tool.objects.get_or_create(name=td)
            tools.append(t)
        return tools

    class Meta:
      model = ToolBox
      exclude  = ('user', 'popularity',)

您必须弄清楚如何修改JavaScript以便输入新项目(即不仅仅是数据库中已有的项目。)

替代解决方案

这是为inline formsets创建的内容,因此Narendra's solution将起作用。

类似的东西:

from django.forms.models import inlineformset_factory

def manage_toolbox(request, toolbox_id):
    toolbox = Toolbox.objects.get(pk=toolbox_id)
    ToolInlineFormSet = inlineformset_factory(Toolbox, Tool)
    if request.method == "POST":
        formset = ToolInlineFormSet(request.POST, request.FILES, instance=toolbox)
        if formset.is_valid():
            formset.save()
            # Do something.
    else:
        formset = ToolInlineFormSet(instance=toolbox)
    return render_to_response("manage_toolbox.html", {
        "formset": formset,
    })

并非此表单仅用于编辑工具箱中的项目。如果您希望用户能够编辑工具箱的其他方面 - 比如它的名称或描述 - 您将创建一个单独的表单并在同一<form></form>标记内输出它们。

答案 1 :(得分:0)

我不确定,因为没有经过测试,但是逻辑就是这样。

  1. 通过formset_factory
  2. 为ToolBoxEditForm创建formset
  3. 将tool_name字段类型更改为CharField
  4. 将formset中的行数精确设置为db
  5. 中可用的Tool对象数
  6. 将首字母传递给formset构造函数以填充tool_name文本框。

    #TODO:必须动态生成以下数据

    initial_data = [{'tool_name':u'first_tool_name',},               {'tool_name':u'second_tool_name',}]

    formset = ToolBoxFormSet(extra = 0,initial = initial_data)

  7. 不确定验证部分。这里我们将tool_name作为textbox的值。在验证期间,Form可能会期望ID(因为它应该是列表框)。但是,你也可以处理它。

    有关formset的更多信息,请参阅:http://docs.djangoproject.com/en/dev/topics/forms/formsets/