Question

By default Django displays date/time as something like May 13th, 2010, 4:01 p.m.. I have also configured a jQuery calendar plugin (I used dateFormat: "MM d, yy", timeFormat: "h:mm tt" and I modified the JavaScript source code to output a.m. and p.m. instead of AM and PM) to display the date/time in the same format.

But the form validation (by default) takes in the form of

DATETIME_INPUT_FORMATS = (
    '%Y-%m-%d %H:%M:%S',     # '2006-10-25 14:30:59'
    '%Y-%m-%d %H:%M:%S.%f',  # '2006-10-25 14:30:59.000200'
    '%Y-%m-%d %H:%M',        # '2006-10-25 14:30'
    '%Y-%m-%d',              # '2006-10-25'
    '%m/%d/%Y %H:%M:%S',     # '10/25/2006 14:30:59'
    '%m/%d/%Y %H:%M:%S.%f',  # '10/25/2006 14:30:59.000200'
    '%m/%d/%Y %H:%M',        # '10/25/2006 14:30'
    '%m/%d/%Y',              # '10/25/2006'
    '%m/%d/%y %H:%M:%S',     # '10/25/06 14:30:59'
    '%m/%d/%y %H:%M:%S.%f',  # '10/25/06 14:30:59.000200'
    '%m/%d/%y %H:%M',        # '10/25/06 14:30'
    '%m/%d/%y',              # '10/25/06'
)

I tried to add '%B %d, %Y, %I:%M %p', but I'm not sure if %p accounts for a.m. and p.m. (notice the periods after the letters). Here is a link to Python's documentation on the date/time formats.

How do you guys do this? Do you just stick with Django's default (ugly) date/time format or do you somehow convert the time before checking for form.is_valid() (whether in JavaScript or Python)?


EDIT for @Thomas Orozco

I wrote a new form field called CustomDateTimeField:

class CustomDateTimeField(forms.DateTimeField):
    def strptime(self, value, format):
        return datetime.datetime.strptime(value.replace("a.m.", "AM").replace("p.m.", "PM"), "%B %d, %Y, %I:%M %p")

However my form uses ModelForm that has a dynamic fields under class Meta. Here is what I mean:

def order_edit(request, pk):
    order = Order.objects.get(pk=pk)

    if foo:
        include_fields = (
            'fa_date',
            'sa_date',
        )
    else:
        include_fields = (
            'sa_date',
        )

    class OrderDetailForm(forms.ModelForm):
        class Meta:
            model = Order
            fields = include_fields

    if request.method == 'POST':
        form = OrderDetailForm(data=request.POST, instance=order)

where Order.sa_date and Order.fa_date are both models.DateTimeField. And I think I can only use DateTimeInput for ModelForm's widgets. So how would I tell the form to use CustomDateTimeField for OrderEditForm? Do I need to add extra arguements via __init__ and manually redefine the fields like self.fields['fa_date'] = CustomDateTimeField(...)?

Was it helpful?

Solution

Initial answer

If you want your field to accept a particular format, the simpler solution would be to implement your own form field, which is usually pretty easy, especially here, given that Django handily provides you with an efficient base class.

Indeed, looking at the django source for the DateTimeField, you can see that it inherits from BaseTemporalField. Therefore, you'll only need to subclass BaseTemporalField and implement the strptime method so that it accepts your input format.

Said input format should be passed to your instance through the input_formats variable, though this wouldn't be a requirement if you're willing to write a little bit more code.

You can also wade through the code for DateTimeField and DateField to get some inspiration.

Edit

You actually can override the fields of a ModelForm: you just have to redefine them. In your situation, you however can't use a conditional block to do so (you can't have a if statement in a class definition!). So you have two solutions:

class SAOrderDetailForm(forms.ModelForm):
    class Meta:
        model = Order
        fields = ('sa_date',)
    sa_date = CustomDateTimeField()

class FASAOrderDetailForm(SAOrderDetailForm): #Inheritance matters!
    class Meta:
        model = Order
        fields = ('sa_date','fa_date')
    fa_date = CustomDateTimeField()

if foo:
    FormClass = FASAOrderDetailForm
else:
    FormClass = SAOrderDetailForm

Alternatively, you could use dynamic creation of form classes , but that's sightly out of the scope of this question, so I'll leave you with this post from James Bennett that explains how to do so.

OTHER TIPS

What %p renders depends on the locale being used. I am not sure if any locale provides for a.m./p.m..

However, the easiest way is to provide your own validation function for your form field. If this is a one-off field, simply override the clean_fieldname(self) method of your form (where fieldname is the name of your datetime field). See cleaning a specific field attribute.

If this field is something you will be re-using, create a custom field with your validation logic and import and use it whenever you need your custom validation. You can also customize the widget to render any jquery selectors as well.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top