Skip to main content
 首页 » 编程设计

python之为什么我的 Django ModelForm 不会引发 unique_together 约束的验证错误

2025年02月15日52insus

我已阅读 Django documentation ModelForm 的 clean() 方法验证了我模型上的 unique_together 约束,如果未验证则引发 ValidationError。但是我的 ModelForm 不这样做。至少它没有在表单中给出错误消息,相反我得到了 Django 错误和回溯:

ValueError at/The Jelentkezes cannot be created because the data didn't validate.

这并不是因为我排除了 unique_together 约束的字段之一。表单的其他验证有效,它们会在表单上给出错误消息。请帮忙,谢谢!

我使用的是 Django 1.10,Python 是 3.5。

我在 models.py 中创建了以下模型:

from django.db import models 
 
class FoglalkozasTipus(models.Model): 
    foglalkozas_tipusa = models.CharField(max_length=255, unique=True) 
 
    def __str__(self): 
        return '%s' % (self.foglalkozas_tipusa) 
 
class Foglalkozas(models.Model): 
    kezdet = models.DateTimeField() 
    veg = models.DateTimeField() 
    foglalkozas_tipusa = models.ForeignKey(FoglalkozasTipus,  
        on_delete=models.CASCADE) 
 
    class Meta: 
        unique_together = (("kezdet", "veg"),) 
        ordering = ['kezdet', 'veg'] 
 
    def __str__(self): 
        return '%s-%s %s' % (self.kezdet.strftime("%Y.%m.%d %H:%M"),  
            self.veg.strftime("%H:%M"), self.foglalkozas_tipusa) 
 
class Jelentkezes(models.Model): 
    foglalkozas = models.ForeignKey(Foglalkozas, on_delete=models.CASCADE) 
    email = models.EmailField() 
    vezeteknev = models.CharField(max_length=255) 
    keresztnev = models.CharField(max_length=255) 
 
    class Meta: 
        unique_together = (("foglalkozas", "email"),) 
 
    def __str__(self): 
        return '%s: %s %s (%s)' % (self.foglalkozas, self.vezeteknev,  
            self.keresztnev, self.email) 

对于 Jelentkezes 模型,我在 forms.py 中创建了一个 ModelForm:

from django.utils import timezone 
from django.forms import ModelForm, RadioSelect 
from .models import Jelentkezes, Foglalkozas 
 
class JelentkezesForm(ModelForm): 
 
    class Meta: 
        model = Jelentkezes 
        fields = ['foglalkozas', 'email', 'vezeteknev', 'keresztnev'] 
        widgets = { 
            'foglalkozas': RadioSelect, 
        } 
 
    def __init__(self, *args, **kwargs): 
        super(JelentkezesForm, self).__init__(*args, **kwargs) 
        self.fields['foglalkozas'].queryset =  
            Foglalkozas.objects.filter(kezdet__gt=timezone.now()) 
        self.fields['foglalkozas'].empty_label = None 

在 views.py 中我使用这个 ModelForm:

from django.shortcuts import render 
from django.http import HttpResponseRedirect 
from .forms import JelentkezesForm 
 
def index(request): 
    if request.method == 'POST': 
        form = JelentkezesForm(request.POST) 
        form.save() 
        return HttpResponseRedirect('koszonet/') 
 
    else: 
        form = JelentkezesForm() 
 
    return render(request, 'aviva/index.html', {'form': form}) 

在 index.html 中,表单看起来像这样(我使用 W3.CSS 框架和 django-widget-tweaks 进行样式设置):

{% load widget_tweaks %} 
 
<form action="" method="post"> 
    {% csrf_token %} 
    {{ form.non_field_errors }} 
    {{ form.foglalkozas.errors }} 
    <label class="w3-label" for="{{ form.foglalkozas.id_for_label }}"><b>{{ form.foglalkozas.label }}:</b></label> 
    {% for radio in form.foglalkozas %} 
    <div class="w3-radio"> 
        {{ radio }} 
    </div> 
    {% endfor %} 
    {{ form.email.errors }} 
    <label class="w3-label" for="{{ form.email.id_for_label }}"><b>{{ form.email.label }}:</b></label> 
    {{ form.email|add_class:"w3-input w3-border w3-round" }} 
    {{ form.vezeteknev.errors }} 
    <label class="w3-label" for="{{ form.vezeteknev.id_for_label }}"><b>{{ form.vezeteknev.label }}:</b></label> 
    {{ form.vezeteknev|add_class:"w3-input w3-border w3-round" }} 
    {{ form.keresztnev.errors }} 
    <label class="w3-label" for="{{ form.keresztnev.id_for_label }}"><b>{{ form.keresztnev.label }}:</b></label> 
    {{ form.keresztnev|add_class:"w3-input w3-border w3-round" }} 
    <p><input type="submit" class="w3-btn w3-blue w3-left w3-border" value="Jelentkezés elküldése" /> 
    <button type="reset" class="w3-btn w3-yellow w3-right w3-border" value="Reset">Űrlapadatok törlése</button></p> 
</form> 

请您参考如下方法:

您永远不会在表单上调用验证。应该是:

if request.method == 'POST': 
    form = JelentkezesForm(request.POST) 
    if form.is_valid(): 
        form.save() 
        return HttpResponseRedirect('koszonet/')