How to create a custom date time widget for the django admin?

非 Y 不嫁゛ 提交于 2019-12-24 01:58:10

问题


My Problem:

I have a model that accepts DateTimeField. The user enters this from the django-admin. But, I cant get a way to get the user's local timezone. So my best shot is forcing the user to enter the date-time in UTC. But for the users convenience, I do not want him/her to calculate each time the offset and then the time in UTC. Django doesn't seem to provide a way of doing this.

What I intend to do:

I want to create a custom widget that will also let the user choose the timezone along with entering the date and time. For this I am using the jQuery datetime picker. I also intend to override the django admin form to have it use this widget of mine.

What I have tried so far:

<!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>

There isnt any action or method because I don't want this widget to post anything anywhere. What it simply does is brings out a nice UI in the browser and lets the user enter a date-time and timezone. So when the user clicks on Done in this jQuery UI the value appears in the textbox of the form.

I seem to have hit a block. Cant think it out at all:

I cant figure out anyway that will let me reference this input by its id or name inside my widgets.py file. widgets.py file is the file where I intend to define the custom widget by extending Widget from *django.forms.widgets*. I read through the docs and figured out that Widget class has two methods of particular importance in this case. The render and value_from_data_dict methods. The former to render the html template and the latter to extract that value from the data dict. (I may be wrong.) But I cant figure out any way to link these two parts of my code. I need help.

Update:

I worked on it but its not working. Heres what I have done till now:

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))

And here is 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"}
        ]
    });       
});
});

What I am stuck at is how do I invoke the javascript from tz_widget.js? In the django admin there is no dropdown or anything. So I am sure the javascript function isnt being called. How can I call it? I dont think I can render it along the html unicode string. Any ideas? I have been at this all night. Need some help please.


回答1:


I think you can create a more generic widget.

First, separate your js, html and media for create a unique widget.

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))"

Now in your admin class, try this:

class YourClassAdmin(admin.ModelAdmin): 
    class Media:
        css = {
            "all": ("my_styles.css",)
        }
        js = ("my_code.js",)

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

    }

If you want to customize your widgets, I suggest you to see the TinyMce widget Code. I know it's a way different but this code helped me to develop my own widgets (https://github.com/aljosa/django-tinymce/tree/master/tinymce)

Django docs is also helpful: https://docs.djangoproject.com/en/1.5/ref/forms/widgets/



来源:https://stackoverflow.com/questions/17584532/how-to-create-a-custom-date-time-widget-for-the-django-admin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!