Skip to content

Instantly share code, notes, and snippets.

@mateuspadua
Last active July 19, 2022 14:03
Show Gist options
  • Save mateuspadua/50a843834a201bede1a0ab239d9fa877 to your computer and use it in GitHub Desktop.
Save mateuspadua/50a843834a201bede1a0ab239d9fa877 to your computer and use it in GitHub Desktop.
Create a DateTimeField managed by MySQL and not by Django.
from datetime import datetime
from django.db.backends.mysql.base import DatabaseWrapper as MySQLDatabaseWrapper
class DBTimestampAutoNowField(models.DateTimeField):
"""
Cria um DateTimeField que é representado no banco de dados como um TIMESTAMP,
que é atualizado a cada modificação na instância, com a data atual com uma precisão
de milisegundos.
Essa atualização é gerenciada pelo próprio MySQL e não pelo Django, garantindo
assim a precisão do valor de cada atualização.
"""
def __init__(self, *args, **kwargs):
"""
Precisa ser null = False, para que o MySQL ao receber um valor None de um
.save() por exemplo, não salve NULL no banco, mas sim a data atual.
Ele faz isso sozinho se o campo for NOT NULL.
"""
kwargs["null"] = False
super().__init__(*args, **kwargs)
def db_type(self, connection):
if isinstance(connection, MySQLDatabaseWrapper):
return (
"TIMESTAMP(6) NOT NULL default CURRENT_TIMESTAMP(6) "
"on update CURRENT_TIMESTAMP(6)"
)
return super().db_type(connection)
def get_db_prep_value(self, value, connection, prepared=False):
# É preciso passar para o banco de dados o valor None (NULL) para assim
# o MySQL entender que ele deve usar a data atual do server neste campo.
if isinstance(connection, MySQLDatabaseWrapper):
return None
# Usa uma data impossível para ter certeza que não estamos salvando nada de
# errado no banco quando for MySQL.
fixed_value = datetime(1900, 1, 1, 0, 0, 0)
return super().get_db_prep_value(fixed_value, connection, prepared)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment