dkhaupt dkhaupt - 3 months ago 11
Python Question

Django admin: rendering page to add new object fails only when datetime field is included in fieldset

I've been working on a Django app to replace a spreadsheet-based sports picking game I play with some friends. I defined my Game model a while ago, but recently added a datetime field to signify the starting time of the game/match:

class Game(models.Model):
home_team = models.CharField(max_length=100, default='---')
away_team = models.CharField(max_length=100, default='---')
spread = models.FloatField(default=0)
week = models.IntegerField(default=0)
home_team_score = models.IntegerField(default=0)
away_team_score = models.IntegerField(default=0)
start_time = models.DateTimeField(default='2015-09-01 13:00:00')

def has_started(self):
if datetime.now() >= self.start_time:
return True
return False
def __str__(self):
return '%s vs. %s, week: %i' % (self.home_team, self.away_team, self.week)


I just noticed that when I use the Django admin functionality to add a new Game, the creation page errors out. However, if I click on an existing Game, the page displays fine, and I can edit the starting time as expected.

The error thrown is:

AttributeError at /admin/app/game/add/
'str' object has no attribute 'date'


Some searching returned similar issues, however they were related to definining the datetime field with
auto_now
or
auto_now_add
as
True
, so the fix is to make sure it handles those fields as read-only.

This situation is different, as if I define a custom
fieldset
in admin.py, that doesn't include the time field, the creation page does not error out when I click to add a new one. For example:

class GameAdmin(admin.ModelAdmin):
fieldsets = [
('League week', {'fields': ['week'], }),
('Teams', {'fields': ['home_team', 'away_team'], }),
('Spread', {'fields': ['spread'], }),
]

list_filter = ['week']
search_fields = ['home_team','away_team']


This works just fine to add a new Game, and I can go back to the default admin layout to change the default time.

I thought I might need to import date from datetime, but adding that didn't help. Is there a different way I need to define my fieldset in order to handle dates properly?

Answer

Set default attribute of start_time to an object of datetime.datetime i.e. datetime.datetime.now() or in your case

datetime.datetime(year=2015, month=9, day=1, hours=13)

Although it is considered good practise to use current/dynamic time as default by setting

default = datetime.datetime.now

or

default = django.utils.timezone.now

for timezone aware datetime (see brackets () are absent after .now), but it depends on your use case.