Date format in modelform.

1,718 views
Skip to first unread message

zayatzz

unread,
Aug 3, 2009, 2:08:57 PM8/3/09
to Django users
Hello.

I have this in my form (modelform) for birth_date field:
birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
required=False ), which overrides this in model:

birth_date = models.DateField(help_text="birth date",
verbose_name="Birth date", blank=True, null=True, )

I also have jquery datepicker on the page which sets date in the same
format (%d/%m/%Y). But the form saves date in %Y-%m-%d format in
database, which means that when user returns to reedit the data, the
form wont validate and the user has to set the date again.

Can anyone tell me what causes such behaviour and how to fix/change
it? My database in mysql - no idea if this is relevant.

Alan

cootetom

unread,
Aug 3, 2009, 4:14:36 PM8/3/09
to Django users
I've always solved this problem in javascript. Plus if you're using
jquery it's a bit easier. Before you set the date picker just format
the date:

$('input#id_date').val($('input#id_date').val().replace(/(\d+)-(\d+)-
(\d+)/ig, '$3/$2/$1')).datepicker({showOn: 'focus', dateFormat: 'dd/mm/
yy'});

Hope that helps. I would also like to know if the output format can be
changed from django.

Malcolm Tredinnick

unread,
Aug 3, 2009, 7:21:59 PM8/3/09
to django...@googlegroups.com
On Mon, 2009-08-03 at 11:08 -0700, zayatzz wrote:
> Hello.
>
> I have this in my form (modelform) for birth_date field:
> birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
> required=False ), which overrides this in model:
>
> birth_date = models.DateField(help_text="birth date",
> verbose_name="Birth date", blank=True, null=True, )
>
> I also have jquery datepicker on the page which sets date in the same
> format (%d/%m/%Y). But the form saves date in %Y-%m-%d format in
> database,

That isn't quite correct. Databases do not save datetimes as strings in
any particular format. They save them as some kind of internal object.

What you are seeing is that the widget rendering is using the %Y-%m-%d
format for some reason. You should investigate that part of the code
more closely. It won't involve the database at all (although it might be
the path of creating a form from your model data that shows the issue --
so try to simulate that without using the database at all).

Regards,
Malcolm


Karen Tracey

unread,
Aug 3, 2009, 7:24:47 PM8/3/09
to django...@googlegroups.com

The format the existing date is displayed in is controlled by the field's widget (it has nothing to do with how the data is stored in the database).  You want to specify a DateInput widget with a format that matches what the field is expecting for input:

http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.DateInput

Note "new in development version" there means new in 1.1.  I think that was in the 1.1 beta actually.

Karen

Margie

unread,
Aug 3, 2009, 10:19:59 PM8/3/09
to Django users
I did this with a combination of a DateWidget and a small .js file
that calls the jquery datepicker on each widget. I don't use the same
date format as you, but you should be able to modify it to fit your
need.

It's amazing how easy the code below looks, but I can tell you it took
me most of a day to figure out how to use the jquery datepicker, how
to create widgets, and how to just put it all together so that it
works!


class DateWidget(widgets.DateInput):
class Media:
js = ('js/jquery.js',
"js/date.js",
"js/jquery.datePicker.min-2.1.2.js",
"js_custom/date_widget.js",
)

css = {'all' : ('css/date_picker.css', 'css/
date_picker_chipvision.css') }

def __init__(self, attrs={}):
attrs['class'] = 'my_class_to_identify_datewidget'
super(DateWidget, self).__init__(format='%m/%d/%Y',
attrs=attrs)

Then I have a small .js file (js_custom/date_widget.js) that has this:
$(document).ready(function() {
Date.firstDayOfWeek = 0;
Date.format = 'mm/dd/yyyy';
$('.my_class_to_identify_datewidget').datePicker();
});


I'm not sure if settings Date.firstDayOfWeek and Date.format the way I
do is the best way to do it, but I could not figure out how to do it
via params to datePicker.

Anyway, hope this helps.

Margie

zayatzz

unread,
Aug 4, 2009, 2:05:33 PM8/4/09
to Django users
Thanks everybody.

I changed this :
birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
required=False ),

for this :
birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
required=False, widget=forms.DateInput(format='%d/%m/%Y') )

And it all works very good.

But there's something else fishy here.

If i tried this:
birth_date = forms.DateField(label='Birth Date', required=False,
widget=forms.DateInput(format='%d/%m/%Y') )

Then it did not save in correct format again. But guess in which
format did it save?
%m/%d/%Y

Why the hell though? could this be a minor bug in django code?

Alan

zayatzz

unread,
Aug 4, 2009, 2:08:05 PM8/4/09
to Django users
Oh and i will not fix problem in server application with a code in
browser script.

As i understand, javascript should be as unobtrusive as possible and
fixing things that way:
1) is not unobtrusive
2) makes you write too much unnecessary code.

Alan.

Karen Tracey

unread,
Aug 4, 2009, 11:33:11 PM8/4/09
to django...@googlegroups.com
On Tue, Aug 4, 2009 at 2:05 PM, zayatzz <alan.ke...@gmail.com> wrote:

Thanks everybody.

I changed this :
birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
required=False ),

for this :
       birth_date = forms.DateField(('%d/%m/%Y',), label='Birth Date',
required=False, widget=forms.DateInput(format='%d/%m/%Y') )

And it all works very good.

But there's something else fishy here.

If i tried this:
       birth_date = forms.DateField(label='Birth Date', required=False,
widget=forms.DateInput(format='%d/%m/%Y') )

Then it did not save in correct format again. But guess in which
format did it save?
%m/%d/%Y

Why the hell though? could this be a minor bug in django code?

No, it's not a bug in Django.  You removed the parameter that told the Field how to properly interpret the date-value-as-string and turn it into a Python date.

There are two format-type parameters. 

The first, the one passed to the Field, tells the field what formats to try when converting form a date-formatted-as-string (as will be present in POST data) to a Python date object.  This format parameter is a sequence, and the formats in it are tried in order until Python is able to parse the string into a date value (or, until the sequence of formats is exhausted, in which case a ValidationError is raised).

The second, the one passed to the Widget, tells the Widget in what format to output existing dates. This is not a list, it is just a single value: your preferred way of formatting dates for output.

If you want things to work properly, you need to make sure that your Field is going to properly recognize the format you have asked the Widget to output.  So your Field has to have the format you have specified for the Widget in its list of allowed input formats.  But when you removed the ('%d/%m/%Y',) parameter to the Field, you changed things so that the Field will use the default list of input formats:

http://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.DateField.input_formats

None of the formats in the default list are "%d/%m/%Y".  Worse, one of the default formats is "%m/%d/%Y" which will succeed in parsing some dates that are actually in "%d/%m/%Y" format, only the values for day and month will get swapped.  Which is what you saw, I gather.  The fix is to put back the format parameter you had been passing to the DateField: it's necessary for the format you are trying to use, as that is not a format that DateField will be attempting to interpret dates with by default.

Karen

zayatzz

unread,
Aug 5, 2009, 1:55:55 AM8/5/09
to Django users
Thanks Karen!

That was one awesome explanation of how datetime field and its widgets
work.

Could it be made sticky for all the future django beginners to read
who have this kind of problems? I for one will certainly bookmark it
so i can thrown this link to anybody who has similar problem.

Alan
Reply all
Reply to author
Forward
0 new messages