无法覆盖django的默认管理模型

时间:2010-03-05 22:56:36

标签: django django-models django-admin validation

我需要在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)

1 个答案:

答案 0 :(得分:2)

首先,在ModelForm上明确声明字段 - 无论是在管理员内还是外 - 并不意味着不会显示其他字段。您需要在表单的内部fields类中定义excludeMeta元组。如果其他字段都是默认字段,您只需声明要覆盖的字段。

其次,如果您希望自定义字段使用javascript,则需要使用正确的窗口小部件,即django.contrib.admin.widgets.AdminDateWidget。但是,有一种更简单的方法可以做到这一点,根本不是定义自定义字段,而是在表单上定义clean_date方法。