Obliczaj sygnatury czasowe w swojej bazie danych, a nie w swoim kliencie
Ze względów rozsądnych prawdopodobnie chcesz, aby wszystko zostało datetimes
obliczone przez serwer bazy danych, a nie przez serwer aplikacji. Obliczanie znacznika czasu w aplikacji może prowadzić do problemów, ponieważ opóźnienie sieci jest zmienne, klienci doświadczają nieco innego przesunięcia zegara, a różne języki programowania czasami obliczają czas nieco inaczej.
SQLAlchemy pozwala to zrobić, przekazując func.now()
lub func.current_timestamp()
(są one wzajemnymi aliasami), co mówi DB, aby obliczył sam znacznik czasu.
Użyj SQLALchemy's server_default
Dodatkowo, w przypadku domyślnego, w którym już mówisz DB, aby obliczył wartość, generalnie lepiej jest użyć server_default
zamiast default
. To mówi SQLAlchemy, aby przekazał wartość domyślną jako część CREATE TABLE
instrukcji.
Na przykład, jeśli napiszesz skrypt ad hoc na tej tabeli, użycie server_default
oznacza, że nie będziesz musiał martwić się o ręczne dodawanie wywołania znacznika czasu do skryptu - baza danych ustawi go automatycznie.
Zrozumienie SQLAlchemy onupdate
/server_onupdate
SQLAlchemy obsługuje również, onupdate
dzięki czemu za każdym razem, gdy wiersz jest aktualizowany, wstawia nowy znacznik czasu. Ponownie, najlepiej powiedzieć DB, aby obliczył sam znacznik czasu:
from sqlalchemy.sql import func
time_created = Column(DateTime(timezone=True), server_default=func.now())
time_updated = Column(DateTime(timezone=True), onupdate=func.now())
Jest server_onupdate
parametr, ale w przeciwieństwie do server_default
tego nie ustawia on niczego po stronie serwera. Po prostu mówi SQLalchemy, że twoja baza danych zmieni kolumnę, gdy nastąpi aktualizacja (być może utworzyłeś wyzwalacz w kolumnie ), więc SQLAlchemy zapyta o wartość zwracaną, aby mógł zaktualizować odpowiedni obiekt.
Jeszcze jedna potencjalna wpadka:
Możesz być zaskoczony, gdy zauważysz, że jeśli dokonasz wielu zmian w ramach jednej transakcji, wszystkie mają ten sam znacznik czasu. Dzieje się tak, ponieważ standard SQL określa, że CURRENT_TIMESTAMP
zwraca wartości na podstawie początku transakcji.
PostgreSQL zapewnia non-SQL standard statement_timestamp()
i clock_timestamp()
które zrobić zmiany w obrębie transakcji. Dokumenty tutaj: https://www.postgresql.org/docs/current/static/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT
Znacznik czasu UTC
Jeśli chcesz używać sygnatur czasowych UTC, func.utcnow()
w dokumentacji SQLAlchemy znajduje się kod implementacji . Musisz jednak samodzielnie zapewnić odpowiednie funkcje specyficzne dla sterownika.