2009-10-30 69 views
0

排除我有一個模型菜單:unique_together驗證失敗,如果場中的一個從形式

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已經存在於數據庫中。我是否需要在其他地方添加此驗證?哪裏?

編輯: 我寫了對視圖的驗證,它將通知傳遞給模板,這很好,但並不完美。我想重新顯示帶有用戶輸入的表單,以便在不丟失該信息的情況下提供解決問題的機會。有沒有辦法做到這一點?

回答

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

我不確定表單如何知道數據庫中存在哪些唯一值,它只是驗證填充模型所需的字段類型,據我所知。

換句話說,「form.is_valid()」不會保存到數據庫,這是您可以查看保存是否有效的唯一方法。

你必須自己去理解這一點,我很確定,但「unique_together」已經在做它的工作。

2

我會離開loja的形式,但使其成爲一個隱藏的領域。

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

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

你可能將不得不改變你的看法打電話給你getloja()不管請求是post或get。你從來沒有解釋如何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,}) 
+0

但是,我的表單無法提交,因爲該字段不能爲空。這似乎是一個更好的解決方案,但我不知道如何使其工作。我試過用loja = forms.ModelChoiceField(label =「」, queryset = Loja.objects.all(), widget = forms.HiddenInput()) – 2009-10-31 04:20:25

+0

Ricardo,getloja(request,s_loja)在做什麼?你可以發佈嗎? – cethegeek 2009-10-31 04:43:15

+0

哦,我剛剛意識到......'s_loja'是傳遞給視圖的url參數,對嗎? getloja可能只是在做一個'Loja.objects.get(...)'(我只是不知道爲什麼你將請求傳遞給它)。只需將getloja()移到form = MenuForm()之前即可。我會編輯我的答案... – cethegeek 2009-10-31 04:58:06