0

I would like to accept natural language strings into a DateTime field, on a form generated by a Django ModelForm. I found Converting string into datetime, which explains how to convert the input string into a DateTime object. (In this case, I'm using timestring for the conversion, instead of strptime as suggested in the answers, because I want to handle input like 'tomorrow'.) But I can't figure out where code this like should be placed within the ModelForm code. If the conversion code is placed in form_valid, it never gets run, because is_python runs first and complains that the text input is not a DateTime. When I override is_python, I get an error that I think comes from some kind of recursive loop.

Relevant code:

models.py

class Widget(models.Model):

    name = models.CharField(max_length=100)
    widget_date = models.DateTimeField

forms.py

from timestring import Date

class NaturalDateField(forms.DateField):

    def to_python(self, value):
        if not value:
            return none
        return Date(value, tz=timezone.get_current_timezone())

class WidgetForm(forms.ModelForm):

    widget_date = NaturalDateField()

    class Meta:
        model = Widget
        fields = ['name', 'widget_date']

views.py

class WidgetUpdate(UpdateView):
    model = Widget
    form_class = WidgetForm

The error on submit is Invlid date string >>. Tracing the code shows that the initial input string converts correctly (to something like '2014-12-26 00:00:00-08:00'), but then the validate() function from site-packages/django/forms/fields.py runs and that goes back into the timestring package for some reason and tries to run def __eq__(self, other): from Date.py, which I think tries to run Date(other), which fails since other is blank.

What is the best method to accept a text string in a ModelForm and then convert it to a field-specific string such as DateTime to be saved in the database?

Community
  • 1
  • 1
Joel Aufrecht
  • 442
  • 1
  • 5
  • 16

2 Answers2

0

Try reusing builtin django date parsing methods:

class NaturalDateField(forms.DateField):

    def to_python(self, value):
        value = super(NaturalDateField, self).to_python(value)
        return value.replace(tzinfo=timezone.get_current_timezone())
imposeren
  • 4,142
  • 1
  • 19
  • 27
0

Looking at that project, your code will return a timestring.Date object, which Django doesn't know what to do with. You probably just need to get the date value from there:

def to_python(self, value):
    if not value:
        return none
    parsed_date = Date(value, tz=timezone.get_current_timezone())
    return parsed_date.date
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • That worked - also, I had to add in exception handling so that form validation would still work: try: parsed_date = Date(value, tz=timezone.get_current_timezone()) except: raise ValidationError("Could not understand: %s" % value) return parsed_date.date – Joel Aufrecht Dec 26 '14 at 17:08