Skip to content

Commit

Permalink
add jDateTimeField widget for admin
Browse files Browse the repository at this point in the history
  • Loading branch information
Milad Rastian committed Aug 3, 2011
1 parent 92882bb commit 8d035e2
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 35 deletions.
13 changes: 9 additions & 4 deletions README
Expand Up @@ -26,7 +26,7 @@ class Bar(models.Model):
name = models.CharField(max_length=200)
date = jmodels.jDateField()
def __str__(self):
return self.name
return "%s, %s"%(self.name, self.date)
class BarTime(models.Model):
objects = jmodels.jManager()
name = models.CharField(max_length=200)
Expand All @@ -50,9 +50,9 @@ Type "help", "copyright", "credits" or "license" for more information.
>>> mybar.date
jdatetime.date(1390, 5, 12)
>>> Bar.objects.filter(date=today)
[<Bar: foo>]
[<Bar: foo, 1390-05-12>]
>>> Bar.objects.filter(date__gte="1390-5-12")
[<Bar: foo>]
[<Bar: foo, 1390-05-12>]
>>> Bar.objects.filter(date='1363-08-01')
[]
>>> from foo.models import BarTime
Expand All @@ -71,7 +71,7 @@ jdatetime.date(1390, 5, 12)
=== ADMIN INTERFACE USAGE
1. create foo/admin.py

from foo.models import Bar
from foo.models import Bar,BarTime
from django.contrib import admin
import django_jalali.admin.filterspecs #you need to import this for adding filter in admin interface
import django_jalali.admin as jadmin #you need import this for adding jalali calander widget
Expand All @@ -81,4 +81,9 @@ class BarAdmin(admin.ModelAdmin):

admin.site.register(Bar, BarAdmin)

class BarTimeAdmin(admin.ModelAdmin):
list_filter = ['datetime']

admin.site.register(BarTime, BarTimeAdmin)

2. Config admin interface and fire up your django and enjoy using jalali date !
7 changes: 5 additions & 2 deletions admin/__init__.py
@@ -1,7 +1,10 @@
from django_jalali.db.models import jDateField
from django_jalali.db.models import jDateField, jDateTimeField
from django.contrib.admin import options
import django_jalali.admin.widgets
options.FORMFIELD_FOR_DBFIELD_DEFAULTS[jDateField] = {'widget': widgets.AdminjDateWidget }
from django import forms

options.FORMFIELD_FOR_DBFIELD_DEFAULTS[jDateField] = {'widget': widgets.AdminjDateWidget }
options.FORMFIELD_FOR_DBFIELD_DEFAULTS[jDateTimeField] = {'form_class': forms.SplitDateTimeField, 'widget': widgets.AdminSplitjDateTime}
#maybe we can use same time
#models.TimeField: {'widget': widgets.AdminTimeWidget},
#models.DateTimeField: {
Expand Down
42 changes: 19 additions & 23 deletions admin/widgets.py
@@ -1,34 +1,30 @@
from django_jalali import forms
from django_jalali import forms as jforms
from django.utils.translation import ugettext as _
from django import forms
from django.contrib.admin.widgets import AdminTimeWidget
from django.utils.safestring import mark_safe

import settings

class AdminjDateWidget(forms.jDateInput):
class AdminjDateWidget(jforms.jDateInput):
class Media:
js = (settings.ADMIN_MEDIA_PREFIX + "js/jcalendar.js",
settings.ADMIN_MEDIA_PREFIX + "js/admin/jDateTimeShortcuts.js")
def __init__(self, attrs={}, format=None):
super(AdminjDateWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'}, format=format)
super(AdminjDateWidget, self).__init__(attrs={'class': 'vjDateField', 'size': '10'}, format=format)


#class AdminTimeWidget(forms.TimeInput):
# class Media:
# js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js",
# settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js")
#
# def __init__(self, attrs={}, format=None):
# super(AdminTimeWidget, self).__init__(attrs={'class': 'vTimeField', 'size': '8'}, format=format)

#class AdminSplitDateTime(forms.SplitDateTimeWidget):
# """
# A SplitDateTime Widget that has some admin-specific styling.
# """
# def __init__(self, attrs=None):
# widgets = [AdminDateWidget, AdminTimeWidget]
# # Note that we're calling MultiWidget, not SplitDateTimeWidget, because
# # we want to define widgets.
# forms.MultiWidget.__init__(self, widgets, attrs)
#
# def format_output(self, rendered_widgets):
# return mark_safe(u'<p class="datetime">%s %s<br />%s %s</p>' % \
# (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
class AdminSplitjDateTime(forms.SplitDateTimeWidget):
"""
A SplitDateTime Widget that has some admin-specific styling.
"""
def __init__(self, attrs=None):
widgets = [AdminjDateWidget, AdminTimeWidget]
# Note that we're calling MultiWidget, not SplitDateTimeWidget, because
# we want to define widgets.
forms.MultiWidget.__init__(self, widgets, attrs)

def format_output(self, rendered_widgets):
return mark_safe(u'<p class="datetime">%s %s<br />%s %s</p>' % \
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
25 changes: 20 additions & 5 deletions db/models.py
Expand Up @@ -162,14 +162,29 @@ def to_python(self, value):
if value is None:
return value
if isinstance(value, datetime.datetime):
return jdatetime.datetime.fromgregorian(datetime=value)
try :
if value.year < 1700 :
return jdatetime.datetime(value.year, value.month, value.day, value.hour, value.minute, value.second, value.microsecond, value.tzinfo)
else :
return jdatetime.datetime.fromgregorian(datetime=value)
except ValueError :
raise exceptions.ValidationError(self.error_messages['invalid'])
if isinstance(value, datetime.date):
return jdatetime.datetime.fromgregorian(date=value)

try :
if value.year < 1700 :
return jdatetime.datetime(value.year, value.month, value.day)
else :
return jdatetime.datetime.fromgregorian(date=value)
except ValueError :
raise exceptions.ValidationError(self.error_messages['invalid'])
if isinstance(value, jdatetime.datetime):
return value
if isinstance(value, jdatetime.date):
return jdatetime.datetime(value.year, value.month, value.day)
try :
d = jdatetime.datetime(value.year, value.month, value.day)
except ValueError :
raise exceptions.ValidationError(self.error_messages['invalid'])
return d


# Attempt to parse a datetime:
Expand Down Expand Up @@ -246,6 +261,6 @@ def value_to_string(self, obj):
return data

def formfield(self, **kwargs):
defaults = {'form_class': mainforms.DateTimeField}
defaults = {'form_class': forms.jDateTimeField}
defaults.update(kwargs)
return super(jDateTimeField, self).formfield(**defaults)
38 changes: 37 additions & 1 deletion forms/__init__.py
@@ -1,4 +1,4 @@
from django_jalali.forms.widgets import jDateInput
from django_jalali.forms.widgets import jDateInput, jDateTimeInput
from django import forms
import time
import datetime
Expand Down Expand Up @@ -36,3 +36,39 @@ def to_python(self, value):
raise ValidationError(self.error_messages['invalid'])


class jDateTimeField(forms.Field):
widget = jDateTimeInput
default_error_messages = {
'invalid': _(u'Enter a valid date/time.'),
}

def __init__(self, input_formats=None, *args, **kwargs):
super(jDateTimeField, self).__init__(*args, **kwargs)
self.input_formats = input_formats

def to_python(self, value):
"""
Validates that the input can be converted to a datetime. Returns a
Python datetime.datetime object.
"""
if value in validators.EMPTY_VALUES:
return None
if isinstance(value, jdatetime.datetime):
return value
if isinstance(value, jdatetime.date):
return jdatetime.datetime(value.year, value.month, value.day)
if isinstance(value, list):
# Input comes from a SplitDateTimeWidget, for example. So, it's two
# components: date and time.
if len(value) != 2:
raise ValidationError(self.error_messages['invalid'])
if value[0] in validators.EMPTY_VALUES and value[1] in validators.EMPTY_VALUES:
return None
value = '%s %s' % tuple(value)
for format in self.input_formats or formats.get_format('DATETIME_INPUT_FORMATS'):
try:
return jdatetime.datetime(*time.strptime(value, format)[:6])
except ValueError:
continue
raise ValidationError(self.error_messages['invalid'])

32 changes: 32 additions & 0 deletions forms/widgets/__init__.py → forms/widgets.py
Expand Up @@ -38,3 +38,35 @@ def _has_changed(self, initial, data):
pass
return super(jDateInput, self)._has_changed(self._format_value(initial), data)

class jDateTimeInput(widgets.Input):
input_type = 'text'
format = '%Y-%m-%d %H:%M:%S' # '2006-10-25 14:30:59'

def __init__(self, attrs=None, format=None):
super(jDateTimeInput, self).__init__(attrs)
if format:
self.format = format
self.manual_format = True
else:
self.format = formats.get_format('DATETIME_INPUT_FORMATS')[0]
self.manual_format = False

def _format_value(self, value):
if self.is_localized and not self.manual_format:
return formats.localize_input(value)
elif hasattr(value, 'strftime'):
value = datetime_safe.new_datetime(value)
return value.strftime(self.format)
return value

def _has_changed(self, initial, data):
# If our field has show_hidden_initial=True, initial will be a string
# formatted by HiddenInput using formats.localize_input, which is not
# necessarily the format used for this widget. Attempt to convert it.
try:
input_format = formats.get_format('DATETIME_INPUT_FORMATS')[0]
initial = datetime.datetime(*time.strptime(initial, input_format)[:6])
except (TypeError, ValueError):
pass
return super(jDateTimeInput, self)._has_changed(self._format_value(initial), data)

0 comments on commit 8d035e2

Please sign in to comment.