【问题标题】:How to create a custom date time widget for the django admin?如何为 django 管理员创建自定义日期时间小部件?
【发布时间】:2013-07-09 04:52:01
【问题描述】:

我的问题:

我有一个接受DateTimeField 的模型。用户从django-admin 输入。但是,我无法获取用户的本地时区。所以我最好的办法是强迫用户在UTC 中输入日期时间。但为了用户方便,我不希望他/她每次计算偏移量,然后计算UTC 中的时间。 Django 似乎没有提供这样做的方法。

我打算做什么:

我想创建一个custom widget,它还允许用户选择timezone,同时输入datetime。为此,我使用jQuery datetime picker. 我还打算override django admin 表单让它使用我的这个小部件。

到目前为止我所做的尝试:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <title> - jsFiddle demo by ioncache</title>
    <script type='text/javascript' src='http://code.jquery.com/jquery-1.7.1.js'></script>
    <link rel="stylesheet" type="text/css" href="/css/normalize.css">
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js"></script>
    <link rel="stylesheet" type="text/css" href="/css/result-light.css">
    <script type='text/javascript' src="https://raw.github.com/trentrichardson/jQuery-Timepicker-Addon/master/jquery-ui-timepicker-addon.js"></script>
    <link rel="stylesheet" type="text/css" href="https://raw.github.com/trentrichardson/jQuery-Timepicker-Addon/master/jquery-ui-timepicker-addon.css">
    <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/smoothness/jquery-ui.css">
    <style type='text/css'>
    </style>

    <script type='text/javascript'>//<![CDATA[
        $(window).load(function(){
        $(function() {
            $('#date-time-tz').datetimepicker({
            dateFormat: $.datepicker.RFC_2822,
            timeFormat: 'hh:mm:ss z',
            showTimezone: true,
            timezoneList: [
                {"value": "0", "label": "UTC"},
                {"value": "+60", "label": "FRANCE"},
                {"value": "+330", "label": "INDIA"},
                {"value": "-240", "label": "US EAST"},
                {"value": "-420", "label": "US SF"}
            ]
        });       
    });
    });//]]>  
    </script>

    </head>
        <body>
        <form name="time">
            <div style="margin: 15px;">
                <input id="date-time-tz" type="text" value="" name="date-time-tz">
                <input type="submit" value="Submit">
            </div>
        </form>
        </body>
</html>

没有任何actionmethod,因为我不希望这个小部件在任何地方出现post。它所做的只是在浏览器中显示一个漂亮的UI,并让用户输入date-timetimezone。所以当用户点击这个jQuery UI中的Done时,值就会出现在form.textbox

我似乎遇到了障碍。完全想不通:

无论如何我都想不通,我的widgets.py 文件中的idname 会让我reference 这个inputwidgets.py 文件是我打算通过从*django.forms.widgets* 扩展Widget 来实现definecustom widget 的文件。我通读了docs 并发现Widget 类在这种情况下有两种特别重要的方法。 rendervalue_from_data_dict 方法。前者用于呈现 html 模板,后者用于从数据字典中提取该值。 (我可能错了。)但我想不出任何方法来链接我的代码的这两个部分。我需要帮助。

更新:

我研究过它,但它不起作用。这是我到目前为止所做的:

ui/admin.py

class MyModelAdmin(admin.ModelAdmin):
    class Media:
        css = {
                "all": ("style/jquery-ui.css",
                        "style/jquery-ui-timepicker-addon.css",)
            }
        js = ("js/jquery-ui.js",
              "js/jquery-ui-timepicker-addon.js",
              "js/tz_widget.js",)

    formfield_overrides = {
            models.DateTimeField : {'widget': TimezoneDate()},
        }

widgets.py

DATE_FORMAT = "%m-%d-%y"

class TimezoneDate(forms.widgets.Widget):

    def __init__(self, attrs=None):
        super(TimezoneDate, self).__init__(attrs)

    def render(self, name, value, attrs=None):

        if value is None:
            vstr = ''
        elif hasattr(value, 'strftime'):
            vstr = datetime_safe.new_datetime(value).stftime(DATE_FORMAT)
        else:
            vstr = value
        id = "%s" % name
        args = \
            "<input type=\"text\" value=\"%s\" name=\"%s\" id=\"date_time_tz\" />" % \
            (vstr, name)

        return mark_safe(u"\n".join(args))

这里是 tz_widget.js :

$(window).load(function(){
    $(function() {
        $('#date-time-tz').datetimepicker({
        dateFormat: $.datepicker.RFC_2822,
        timeFormat: 'hh:mm:ss z',
        showTimezone: true,
        timezoneList: [
            {"value": "0", "label": "UTC"},
            {"value": "+60", "label": "FRANCE"},
            {"value": "+330", "label": "INDIA"},
            {"value": "-240", "label": "US EAST"},
            {"value": "-420", "label": "US SF"}
        ]
    });       
});
});

我遇到的问题是如何从 tz_widget.js 调用 javascript?在 django 管理员中没有下拉菜单或任何东西。所以我确信javascript函数没有被调用。我怎么称呼它?我不认为我可以沿着 html unicode 字符串呈现它。有任何想法吗?我整晚都在这。需要一些帮助。

【问题讨论】:

    标签: python django django-widget custom-widgets


    【解决方案1】:

    我认为您可以创建一个更通用的小部件。

    首先,将你的 js、html 和媒体分开,以创建一个独特的小部件。

    widgets.py

     class DatTimeField(forms.Textarea):
         def render(self, name, attrs = None):
             final_attrs = self.build_attrs(attrs,name=name)
             return "Here you have to return the html of your widget, for example: mark_safe(u'<input type=text %s value=%s class='your_css_class'/>' % (flatatt(final_attrs), value))"
    

    现在在你的管理类中,试试这个:

    class YourClassAdmin(admin.ModelAdmin): 
        class Media:
            css = {
                "all": ("my_styles.css",)
            }
            js = ("my_code.js",)
    
        formfield_overrides = {
            models.DateTimeField : {'widget': DatTimeField()},
    
        }
    

    如果您想自定义您的小部件,我建议您查看 TinyMce 小部件代码。我知道这是一种不同的方式,但这段代码帮助我开发了自己的小部件 (https://github.com/aljosa/django-tinymce/tree/master/tinymce)

    Django 文档也很有帮助:https://docs.djangoproject.com/en/1.5/ref/forms/widgets/

    【讨论】:

    • 不应该类DateTimeField扩展Widget吗?
    • 你也可以这样做。就像我难过一样,我以 tinymce 小部件为基础,但您可以通过其他方式执行此操作,例如此处的示例:(docs.djangoproject.com/en/1.5/ref/forms/widgets/…)
    • 你能解释一下返回的html字符串吗? flatatt 是什么,final_attrs 由什么组成?
    • @IndradhanushGupta final_attrs 是小部件将以 django 样式显示的属性,例如 id=id_name_of_the_field 和 name=name_of_the_field,还有一些其他属性
    • flatatt -> 转换字符串中的属性字典 (github.com/django/django/blob/master/django/forms/util.py)
    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    相关资源
    最近更新 更多