I have a MySQL database that is used by another application besides Django. That application uses '0000-00-00 00:00:00'
as default value for datetimes.
Django (v1.5.5) interprets '0000-00-00 00:00:00'
datetime as None
when reading the database and None
as NULL
when writing into the database. This causes an error since the database defines the field as NOT NULL
.
Manually setting:
model.datetime = '0000-00-00 00:00:00'
Doesn't work because Django feels that this is an invalid date.
How do I create a custom datetime field which inserts None
as '0000-00-00 00:00:00'
?
building on Seppo's solution (which didn't work for django 1.9.4 because of lacking connection.ops.value_to_db_datetime), I ended up using a custom DateTimeField as follows:
from django.db import models
class ZeroDateTimeField(models.DateTimeField):
def get_db_prep_value(self, value, connection, prepared=False):
value = super( ZeroDateTimeField, self ).get_db_prep_value( value, connection, prepared )
if value is None:
return "0000-00-00 00:00:00"
return value
Then just use ZeroDateTimeField in your models instead of DateTimeField.
works like a charm and I got around having to tell the customer to fix his mysql db ;-)
EDIT: I ended up overriding constructor to set null=True and blank=True to ease use of automatically generated models. Since this may be useful for some, here it is (this is optional and questionable):
def __init__(self, verbose_name=None, name=None, auto_now=False, auto_now_add=False, **kwargs):
kwargs['null'] = True
kwargs['blank'] = True
super( ZeroDateTimeField, self ).__init__(verbose_name, name, auto_now, auto_now_add, **kwargs)
Create a custom DateTimeField
and override the get_db_prep_value
. The method is copypasted from the django source and a case is added for handling None
. The value should be converted in a database specific manner so this is a bit hacky but it works as long as the database accepts 0000-00-00 00:00:00
as a datetime.
from django.db import models
class ZeroDateTimeField(models.DateTimeField):
def get_db_prep_value(self, value, connection, prepared=False):
# Casts datetimes into the format expected by the backend
if not prepared:
value = self.get_prep_value(value)
# Use zeroed datetime instead of NULL
if value is None:
return "0000-00-00 00:00:00"
else:
return connection.ops.value_to_db_datetime(value)
EDIT: This answer was written for Django 1.5 and support with other versions has not been tested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With