无法覆盖 django 的默认管理模型
我需要在管理中向我的日期字段添加额外的验证,以确保给定的日期是将来的日期。我没有这方面的经验,所以这就是我所做的。 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)
I need to add extra validation to my DateField in Admin to make sure the date given is in the future. I have no experience in such a thing, so here's what I've done.
1) I've created custom form field and added validation to it:
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) Then I've added custom model form:
class CustomNewsItemAdminForm(forms.ModelForm):
title = forms.CharField(max_length=100)
body = forms.CharField(widget=forms.Textarea)
date = PastDateField()
region = forms.ModelChoiceField(Region.objects)
3) And here's how I've registered admin:
class NewsItemAdmin(admin.ModelAdmin):
form = CustomNewsItemAdminForm
def queryset(self, request):
return NewsItem.objects.all()
admin.site.register(NewsItem, NewsItemAdmin)
The result of this is that my admin form
1) Shows field I haven't specified in custom admin form
2) Lacks JavaScript calendar for the datetime field
It's pretty obvious to me that I'm doing something wrong, but I've found no examples relevant to my needs as I am a noob. What is the better way to add custom validation to datetime field without messing things up?
EDIT: Thanks a lot to Brian Luft and Daniel Roseman for correct answers! To make this post helpful for someone facing the same problem here is the resulting code:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
首先,在 ModelForm 上显式声明字段(无论是在管理员内部还是在管理员之外)并不意味着其他字段不会显示。您需要在表单的内部
Meta
类中定义fields
或exclude
元组。如果其他字段都是默认的,您可以简单地声明您要覆盖的字段。其次,如果您希望自定义字段使用 JavaScript,则需要使用正确的小部件,即 django.contrib.admin.widgets.AdminDateWidget。但是,有一种更简单的方法可以做到这一点,即根本不定义自定义字段,而是在表单本身上定义一个
clean_date
方法。Firstly, declaring fields explicitly on a ModelForm - whether in or out of the admin - does not mean that the other fields will not be displayed. You need to define the
fields
orexclude
tuples in the form's innerMeta
class. If the other fields are all the default, you can simply declare the one you are overriding.Secondly, if you want your custom field to use the javascript, you'll need to use the right widget, which is
django.contrib.admin.widgets.AdminDateWidget
. However, there is a much easier way to do this, which is not define a custom field at all, but instead define aclean_date
method on the form itself.