当前位置:  开发笔记 > 后端 > 正文

如何更改ModelForm中所有Django日期字段的默认小部件?

如何解决《如何更改ModelForm中所有Django日期字段的默认小部件?》经验,为你挑选了3个好方法。

给出一组典型的模型:

# Application A
from django.db import models
class TypicalModelA(models.Model):
    the_date = models.DateField()

 # Application B
from django.db import models
class TypicalModelB(models.Model):
    another_date = models.DateField()

...

如何将所有 DateFields 的默认小部件更改为自定义MyDateWidget?

我问,因为我希望我的应用程序有一个jQueryUI datepicker用于输入日期.

我考虑过一个自定义字段,它使用我的自定义小部件扩展django.db.models.DateField.这是实施这种全面改变的最佳方式吗?这样的改变需要专门将一个特殊的MyDateField导入到每个模型中,这是一个劳动密集型,容易出现开发人员错误(即一些模型.DateField将会通过),在我看来似乎是不必要的重复工作.另一方面,我不喜欢修改可以被认为是规范版本的模型.DateField.

感谢思想和投入.



1> James Bennet..:

您可以在ModelForm类上声明一个名为的属性formfield_callback.这应该是一个将Django模型Field实例作为参数的函数,并返回一个表单Field实例以在表单中表示它.

然后,您要做的就是查看传入的模型字段是否为实例DateField,如果是,则返回自定义字段/窗口小部件.如果没有,模型字段将具有一个名为的方法formfield,您可以调用该方法返回其默认表单字段.

所以,像:

def make_custom_datefield(f):
    if isinstance(f, models.DateField):
        # return form field with your custom widget here...
    else:
        return f.formfield()

class SomeForm(forms.ModelForm)
    formfield_callback = make_custom_datefield

    class Meta:
        # normal modelform stuff here...


如果这是您在使用DateTimeFields的多个表单中需要的常见行为,那么这是干嘛的方法.
谢谢,詹姆斯.这帮了很多忙.我在我的博客上提出了我的实施的完整示例(http://strattonbrazil.blogspot.com/2011/03/using-jquery-uis-date-picker-on-all.html).
快速警告以节省其他时间.如果从定义formfield_callback的自定义基本表单类继承,则不会调用BaseForm.formfield_callback.这是因为formfield_callback被调用为__new__的一部分(即,在ModelFormMetaClass中).我为此问题创建了一个不错的解决方法,如果您感兴趣,可以在此处找到:http://stackoverflow.com/questions/7342925/django-problem-inheriting-formfield-callback-in-modelforms/12204640#12204640.

2> Soviut..:

这篇文章曾多次帮助过我.

它的内容涉及覆盖ModelForm的__init__方法,然后调用超类的__init__方法,然后单独调整字段.

class PollForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PollForm, self).__init__(*args, **kwargs)
        self.fields['question'].widget = forms.Textarea()

    class Meta:
        model = Poll

这种方法看起来可能比Vasil更复杂,但它提供了额外的好处,即能够精确覆盖字段上的任何属性,而无需通过重新声明来重置任何其他属性.

更新:建议的方法可以推广到更改所有日期字段而不严格键入每个名称:

from django.forms import fields as formfields
from django.contrib.admin import widgets

class PollForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PollForm, self).__init__(*args, **kwargs)
        for field_name in self.fields:
            field = self.fields[field_name]
            if isinstance(field, formfields.DateField):
                field.widget = widgets.AdminDateWidget()

    class Meta:
        model = Poll

这为我工作的python3,并django 1.11



3> Vasil..:

好吧,制作一个自定义模型字段只是为了改变它的默认表单小部件并不是一个明显的起点.

您可以创建自己的表单窗口小部件并覆盖表单中的字段,在Soviut的答案中指定您自己的窗口小部件.

还有一个更短的方式:

class ArticleForm(ModelForm):
     pub_date = DateField(widget=MyDateWidget())

     class Meta:
         model = Article

有一个如何编写表单小部件的例子,它位于Django的表单包中.这是一个有3个下拉菜单的日期选择器.

当我只想将一些JavaScript添加到标准HTML输入元素时,我通常会做的就是保持原样并通过稍后使用JavaScript引用它来修改它.您可以轻松捕获Django生成的输入字段的ID的命名约定.

您还可以在窗体中覆盖窗口小部件时为窗口小部件提供类.然后用类名用jQuery捕获它们.

推荐阅读
谢谢巷议
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有