如何在表单验证错误发生时指定它们?

时间:2011-12-11 16:21:16

标签: python django django-forms

我是Django Forms的新手,我遇到了一个我无法解决的问题。我一直在谷歌搜索和阅读文档,但我找不到这个解释的地方。我的问题是我有一个 Animal Model和一个ModelForm

class Animal(models.Model):
    name = models.CharField(max_length=300)
    age = models.PositiveSmallIntegerField()
    race = models.ForeignKey(Race)
    description = models.TextField()
    state = models.ForeignKey(State)
    pub_date = models.DateTimeField(auto_now_add=True)
    adoption_limit = models.DateTimeField(blank=True, null=True)
    location = models.ForeignKey(Location)
    publisher = models.ForeignKey(User)
    def __unicode__(self):
        return self.name

class AnimalForm(ModelForm):
    class Meta:
        model = Animal

我通过urls.py呈现此信息,调用此视图:

@login_required
def new_animal(request):
    if request.method == "POST":
        form = AnimalForm(request.POST)
        if form.is_valid():
            form.save()
            return render_to_response('/')
        else:
            variables = RequestContext(request, {'e': form.errors})
            return render_to_response('web/error.html', variables)
    else:
        form = AnimalForm()
    variables = RequestContext(request, {'form': form})
    return render_to_response('web/animal_form.html', variables)

似乎我在引入adoption_limit字段时出错,因此数据不会保存在DB中。这是因为我只是在表单显示的文本字段中设置了日期而不是时间。

我想知道如何做两件事:

  1. 如何再次将错误消息发送到表单,以便我可以在未正确设置的字段旁边添加文本?就像管理员一样。
  2. 如何为管理界面中的DateTimeField添加相同的输入类型? (使用今日和现在的功能)

2 个答案:

答案 0 :(得分:4)

您在web/error.html模板中编写视图以显示表单错误的方式只是输出错误:

{%if e %}
  You had some errors in your submission!<br />
  {{ e }}
{% endif %}

但是,您没有显式传递错误列表,它是表单本身的一部分。一点简化:

variables = RequestContext(request, {'form': form})
return render_to_response('web/error.html', variables)

然后,在您的模板中:

{% if form.errors %}
   You have some errors!<br />
   {{ form.errors }}
{% endif %}

对于你问题的第二部分 - 显示django日期时间小部件 - 事情会更复杂:

# First, you need to import the widget:
from django.contrib.admin.widgets import AdminSplitDateTime
from django.forms import TextField

# In your form class, you have to specify the widget
# for the field.

class AnimalForm(forms.ModelForm):
   pub_date = models.TextField(widget=AdminSplitDateTime)
   class Meta:
      model = Animal

为了实现这一点,你必须确保你的项目可以访问你的管理媒体目录(因为那里包含了所有的javascript和css)。您还要确保还添加了所有样式表。从您喜欢的库中使用您自己的javascript表单小部件会更容易(也更简单)。

最后,正如documentation中所述,如果覆盖任何字段,则需要自己添加所有其他验证逻辑:

  

如果你明确地实例化这样的表单字段,Django假设   你想要完全定义它的行为;因此,默认   属性(例如max_length或required)不是从中提取的   相应的模型。如果要保持指定的行为   在模型中,您必须明确设置相关参数   声明表单字段。

答案 1 :(得分:0)

burhan的回答很明显。另外,您可能希望隐藏表单上的发布者并在您的视图中处理它。

为此,请将exclude =('publisher',)添加到ModelForm中的类Meta。

然后在你看来:

if form.is_valid():
    animal = form.save(commit=false)
    animal.publisher = request.user
    animal.save()

否则,我认为您的表单会在下拉列表中显示所有用户,这可能不是您想要的。