Django 如果表单中排除了其中一个字段,则unique_together验证将失败

Django 如果表单中排除了其中一个字段,则unique_together验证将失败,django,django-forms,Django,Django Forms,我有一个模型菜单: 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',)

我有一个模型菜单:

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
    })
错误:(在addmenu视图上添加验证后不再发生)

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

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

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

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


我很确定,你必须自己去发现这个问题,但是“unique_together”已经在做它的工作了。

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

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


我敢肯定,你必须自己去捕捉这个,但是“unique_together”已经在做它的工作了。

我只想把
loja
留在表单中,但把它变成一个隐藏字段

class MenuForm(ModelForm):
    loja = models.ModelChoiceField(Loja.objects.all(), widget=forms.HiddenInput)

    class Meta:
        model = Menu
        exclude =('ordenacao',)
无论请求是post还是get,您可能都必须更改视图以调用
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
,但将其设为隐藏字段

class MenuForm(ModelForm):
    loja = models.ModelChoiceField(Loja.objects.all(), widget=forms.HiddenInput)

    class Meta:
        model = Menu
        exclude =('ordenacao',)
无论请求是post还是get,您可能都必须更改视图以调用
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,})

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

@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,
    })

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

@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,
    })

但是我不能提交表单,因为字段不能为空。这似乎是一个更好的解决方案,但我不知道如何让它起作用。我试过使用loja=forms.modelcooicefield(label=”“,queryset=loja.objects.all(),widget=forms.HiddenInput())Ricardo,getloja(请求,s_loja)在做什么?你能把它贴出来吗?哦,我刚意识到
s_loja
是否将url参数传递到视图中,对吗?getloja可能只是在做一个
Loja.objects.get(…)
(我只是不知道为什么要将请求传递给它)。只需将getloja()移到form=MenuForm()之前的右边。我将编辑我的答案…现在查看我答案中的视图代码。。。我仍然不知道为什么
getloja()
需要请求……隐藏字段的想法听起来不错,但似乎不起作用。唯一可行的方法是我不验证表单,但是我不能提交表单,因为字段不能为空。这似乎是一个更好的解决方案,但我不知道如何让它起作用。我试过使用loja=forms.modelcooicefield(label=”“,queryset=loja.objects.all(),widget=forms.HiddenInput())Ricardo,getloja(请求,s_loja)在做什么?你能把它贴出来吗?哦,我刚意识到
s_loja
是否将url参数传递到视图中,对吗?getloja可能只是在做一个
Loja.objects.get(…)
(我只是不知道为什么要将请求传递给它)。只需将getloja()移到form=MenuForm()之前的右边。我将编辑我的答案…现在查看我答案中的视图代码。。。我仍然不知道为什么
getloja()
需要请求……隐藏字段的想法听起来不错,但似乎不起作用。唯一可行的方法是我不验证表单。