我需要在Admin中为我的DateField添加额外的验证,以确保给定的日期是将来的。我没有这方面的经验,所以这就是我所做的。 1)我已经创建了自定义表单字段并添加了验证:
class PastDateField(forms.DateField):
def clean(self, value):
"""Validates if only date is in the past
"""
if not value:
raise forms.ValidationError('Plase enter the date')
if value > datetime.now():
raise forms.ValidationError('The date should be in the past, not in future')
return value
2)然后我添加了自定义模型表单:
class CustomNewsItemAdminForm(forms.ModelForm):
title = forms.CharField(max_length=100)
body = forms.CharField(widget=forms.Textarea)
date = PastDateField()
region = forms.ModelChoiceField(Region.objects)
3)以下是我注册管理员的方式:
class NewsItemAdmin(admin.ModelAdmin):
form = CustomNewsItemAdminForm
def queryset(self, request):
return NewsItem.objects.all()
admin.site.register(NewsItem, NewsItemAdmin)
结果就是我的管理员表格 1)显示我未在自定义管理员表单中指定的字段 2)缺少日期时间字段的JavaScript日历
我很明显我做错了什么,但我发现没有与我的需求相关的例子,因为我是一个菜鸟。将自定义验证添加到日期时间字段而不搞乱的更好方法是什么?
编辑:非常感谢Brian Luft和Daniel Roseman的正确答案!为了使这篇文章对面临同样问题的人有帮助,最终的代码是:
class CustomNewsItemAdminForm(forms.ModelForm):
class Meta:
model = NewsItem
def clean_date(self):
"""Validates if only date is in the past
"""
date = self.cleaned_data["date"]
if date is None:
raise forms.ValidationError('Plase enter the date')
if date > datetime.now().date():
raise forms.ValidationError('The date should be in the past, not in future')
return self.cleaned_data["date"]
class NewsItemAdmin(admin.ModelAdmin):
form = CustomNewsItemAdminForm
def queryset(self, request):
return NewsItem.objects.all()
admin.site.register(NewsItem, NewsItemAdmin)
答案 0 :(得分:2)
首先,在ModelForm上明确声明字段 - 无论是在管理员内还是外 - 并不意味着不会显示其他字段。您需要在表单的内部fields
类中定义exclude
或Meta
元组。如果其他字段都是默认字段,您只需声明要覆盖的字段。
其次,如果您希望自定义字段使用javascript,则需要使用正确的窗口小部件,即django.contrib.admin.widgets.AdminDateWidget
。但是,有一种更简单的方法可以做到这一点,根本不是定义自定义字段,而是在表单上定义clean_date
方法。