问题
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