7

I have a model that looks something like this

class Post(models.Model):
    id = models.IntegerField(unique=True, primary_key=True)
    title = models.CharField(max_length=150, blank=True)
    created = models.DateTimeField(blank=True)
    ...

I have to fill the database with chunks of data. I am getting the data in form of a flat json string (no nesting) so my work is pretty easy i.e.

mydict = json.loads(jsonstr)
mypost = Post(**mydict) 
mypost.save()

there is just one issue that the date-time is expressed in "YYYY-MM-DDThh:mm:ss+zzzz" format ( e.g. "created" : "2011-11-17T09:21:31+0000" ) which breaks the above code.

I know forms.DateTimeField has input_formats. Is there a way I could make DateTimeField accept above format?

Optimus
  • 2,716
  • 4
  • 29
  • 49

4 Answers4

7

Subclass DateTimeField and convert the value appropriately:

class ConvertingDateTimeField(models.DateTimeField):

    def get_prep_value(self, value):
        return str(datetime.strptime(value, FORMAT_STRING))

Then use ConvertingDateTimeField to replace models.DateTimeField.

There's probably a better way to do it if you look how DateTimeField creates the datetime object.

scriptboy
  • 777
  • 8
  • 25
Chris Lacasse
  • 1,502
  • 10
  • 10
  • 1
    Thanks for the answer, I knew I had to subclass DateTimeField but couldn't find the method to override. It really helped. – Optimus Nov 18 '11 at 21:48
3

You can use a ModelForm and override the created form field instead of going directly to your model.

Something like this:

from django.forms import ModelForm

class PostForm(ModelForm):
    created = forms.DateTimeField(input_formats=('%Y-%m-%dT%H:%M:%S+0000',))
    class Meta:
        model = Post

mydict = ...

form = PostForm(mydict)
if not form.is_valid():
    # handle appropriately for your app
    raise Exception

instance = form.save() # or use 'commit=False' if you don't want to save to DB

Unfortunately, I don't think strptime supports the GMT offset hence why I've hard-coded it in the input_format. You may be able to override the 'clean' method for that field if you want to scrub it yourself.

Joe Holloway
  • 28,320
  • 15
  • 82
  • 92
1

I believe the DateTimeField expects a timezone-naive datetime, so you need to strip off the (+zzzz) part.

naive = dt.replace(tzinfo=None)

Applies to Python 2.x only.

Community
  • 1
  • 1
Tom
  • 22,301
  • 5
  • 63
  • 96
  • striping off the timezone info does not solve my problem completely i would still need to do a bunch of string operations before django accepts it, which i am looking to avoid that's why i asked the question in the first place – Optimus Nov 17 '11 at 18:24
  • It's sad that python has such poor support for timezone info. I mean it is simple enough to convert date time to gmt for saving into any database. But, I still love python :) – Optimus Nov 18 '11 at 21:57
0

ok this is what i did finally :

class MyDateTimeFeild(models.DateTimeField):
    def get_prep_value(self, value):
        from dateutil.parser import parse
        from datetime import timedelta
        td = float(value[-5:])/100
        timediff = timedelta(hours=td)
        return parse(value).replace(tzinfo=None) - timediff

thanks every one!! :) all posts were very helpfull.

Optimus
  • 2,716
  • 4
  • 29
  • 49