【问题标题】:Django embedded ManyToMany formDjango 嵌入多对多表单
【发布时间】:2011-02-17 23:47:31
【问题描述】:

我需要一个特殊的部分到一个我现在无法想象该怎么做的表格中。我会尽量说清楚。

假设我有一个像“Sale”这样的模型。这自然是一组正在销售的产品。我不想选择ManyToMany上的产品,我只想有两个CharFields,比如“名称”和“价格”,以及一个“添加”按钮。当我填写这些字段并按“添加”时,将有一个 ajax 操作将一行放入它们正下方的框中。如果我想通过单击该行中的“删除”按钮来删除其中一行,也是如此。

这基本上是一个多对多字段,我可以“即时”插入它们。

我也完全愿意接受其他解决方案。 谢谢。

【问题讨论】:

    标签: django forms admin


    【解决方案1】:

    如果它适合你,整个事情都可以用 javascript 轻松完成。为创建/编辑/删除创建处理程序。 Create 为 GET 呈现一个空白表单并为 POST 验证/保存,将新项目添加到它应该属于的销售中。编辑/删除应该很明显。

    我可能只是让处理程序呈现 html 部分,使用 javascript 将 html 拉入 dom 以进行 GET 并使用 POST 更改数据到服务器。

    假设模型,

    class Sale(models.Model):
      items = models.ManyToMany('Item', related_name='sales')
      # ...
    
    class Item(models.Model):
      # ...
    

    然后我们可以像这样创建一些处理程序:

    def create_item(request, saleID=""):
      sale = get_object_or_404(Sale, <ID>=saleID) # <- get the sale obj
    
      if request.method == 'POST':
        form = ItemForm(request.POST) # <- could take the sale here and do .add() in the save()
        if form.is_valid():
          i = form.save()
          sale.items.add(i) # <- or, add in the view here
          if request.is_ajax():
            return HttpResponse('ok')
          # redirect with messages or what have you if not ajax
      else:
        # make a blank form and whatnot
      # render the form
    
    def edit_item(request, id|pk|slug=None):
      item = get_object_or_404(Item, slug=slug)
      if request.method == 'POST':
        # do the form is_valid, form save, return 'ok' if ajax, redirect if not ajax
      else:
        form = EditForm(instance=item)
      # render the form
    
    def delete_item(request, id|pk|slug=None):
      if request.method == 'POST':
        # delete the item and redirect, or just return "ok" if is_ajax
      # render confirmation dialog
    

    对于前端代码,我会使用 http://api.jquery.com/load/ http://api.jquery.com/jQuery.get/ 和 http://api.jquery.com/jQuery.post/ 等的组合,但任何 javascript 框架都可以。

    【讨论】:

    • 大声笑,有人在 2014 年 5 月对此投了反对票……嗯 .. 是的,现在可能有更好的方法可以做到这一点,idk :D。