【问题标题】:unique_together validation fails if one of the fields is excluded from form如果其中一个字段从表单中排除,则 unique_together 验证失败
【发布时间】:2010-12-11 18:24:27
【问题描述】:

我有一个模型菜单:

class Menu(models.Model):
    loja = models.ForeignKey(Loja, related_name='menus')
    nome = models.CharField(max_length=30)
    ordenacao = models.IntegerField(blank=True, null=True)

    class Meta:
        ordering = ('ordenacao',)
        #prevent equally named menus within a store(loja)
        unique_together = ('loja', 'nome')

    def __unicode__(self):
        return self.nome 

菜单表单:

class MenuForm(ModelForm):
    class Meta:
        model = Menu
        exclude =('loja', 'ordenacao',)

添加菜单视图:

def addmenu(request, s_loja):
    loja = get_object_or_404(Loja, slug=s_loja)
    if not loja.activo:
        return render_to_response('painelcontrolo/loja_detail.html', {
            'notificacoes': ['Loja está definida como inactivo.', \
                             'Alterações não permitidas']})
    if request.method == 'POST':
        menu = Menu(loja=loja)
        form = MenuForm(request.POST, instance=menu)
        if form.is_valid():
            menu_existe = Menu.objects.\
                          filter(nome=form.cleaned_data['nome']).\
                          filter(loja=loja)
            if menu_existe:
                return render_to_response(\
                    'painelcontrolo/loja_detail.html', {
                        'notificacoes': ['Já existe um menu com esse nome']
                        })
            form.save()
            return render_to_response(\
                    'painelcontrolo/loja_detail.html', {
                        'notificacoes': ['Menu adicionado']
                        })
    else:
        form = MenuForm()
    return render_to_response('form_as_p.html', {
        'form': form
    })

错误:(在添加菜单视图上添加验证不再发生)

Request Method:     POST
Request URL:    http://127.0.0.1:8000/painel/bispos/addmenu/
Exception Type:     IntegrityError
Exception Value:    columns loja_id, nome are not unique

问题: 表单有效,但如果数据库上已经存在 nome+loja_id,则模型无效。我是否需要在其他地方添加此验证?在哪里?

编辑: 我在视图上写了一个验证,它将通知传递给模板,这很好,但并不完美。我想重新显示带有用户输入的表单,以便在不丢失该信息的情况下修复错误。有没有办法做到这一点?

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    好的,这是我能想到的最好的了。它在表单上给出了错误,并且似乎工作正常。

    @login_required
    def addmenu(request, s_loja):
        loja = get_object_or_404(Loja, slug=s_loja)
        if not loja.activo:
            return render_to_response('painelcontrolo/loja_detail.html', {
                'notificacoes': ['Loja está definida como inactivo.', \
                                 'Alterações não permitidas']})
        if request.method == 'POST':
            menu = Menu(loja=loja)
            form = MenuForm(request.POST, instance=menu)
            if form.is_valid():
                menu_existe = Menu.objects.\
                              filter(nome=form.cleaned_data['nome']).\
                              filter(loja=loja)
                if not menu_existe:
                    form.save()
                    return render_to_response('painelcontrolo/loja_detail.html', {
                            'notificacoes': ['Menu adicionado']
                            })
                else:
                    form._errors['nome'] = ErrorList(\
                        ['Um menu com esse nome já existe'])
        else:
            form = MenuForm()
        return render_to_response('form_as_p.html', {
            'form': form,
        })
    

    【讨论】:

      【解决方案2】:

      我只是将loja 留在表单中,但将其设为隐藏字段。

      class MenuForm(ModelForm):
          loja = models.ModelChoiceField(Loja.objects.all(), widget=forms.HiddenInput)
      
          class Meta:
              model = Menu
              exclude =('ordenacao',)
      

      无论请求是发布还是获取,您可能都必须更改视图以致电您的getloja()。你永远不会解释 getloja() 如何决定什么是正确的实例......

      @login_required
      def addmenu(request, s_loja):
          if request.method == 'POST':
              form = MenuForm(request.POST)
              if form.is_valid():
                  form.save()
                  return HttpResponseRedirect('/painel/profile/')
          else:
              loja = getloja(request, s_loja) #simply retrieves the correct loja instance
              menu = Menu(loja=loja)
              form = MenuForm(instance=menu)
          return render_to_response('form_as_p.html', {
                 'form': form,})
      

      【讨论】:

      • 然后我的表单无法提交,因为该字段不能为空。这似乎是一个更好的解决方案,但我不确定如何使其工作。我试过 loja = forms.ModelChoiceField(label="", queryset=Loja.objects.all(), widget=forms.HiddenInput())
      • 里卡多,getloja(request, s_loja) 在做什么?可以发一下吗?
      • 哦,我才意识到...s_loja是传入视图的url参数,对吗? getloja 可能只是在做一个Loja.objects.get(...)(我只是不知道你为什么将请求传递给它)。只需将 getloja() 移到 form=MenuForm() 之前。我将编辑我的答案...
      • 现在看我回答中的视图代码...我仍然不知道为什么getloja()需要请求...
      • 隐藏字段的想法听起来不错,但似乎不起作用。唯一可行的方法是如果我不验证表单。
      【解决方案3】:

      我不确定表单如何知道数据库中存在哪些唯一值,据我所知,它只是验证填充模型所需的字段类型。

      换句话说,“form.is_valid()”不会保存到数据库中,这是查看保存是否有效的唯一方法。

      我很确定,你必须自己解决这个问题,但“unique_together”已经在发挥作用了。

      【讨论】:

        猜你喜欢
        • 2011-10-17
        • 2020-08-03
        • 1970-01-01
        • 2014-06-14
        • 2023-03-15
        • 2015-11-22
        • 2017-09-24
        • 2020-12-23
        • 1970-01-01
        相关资源
        最近更新 更多