Porównaj ceny domen i usług IT, sprzedawców z całego świata

SqlAlchemy TIMESTAMP „przy aktualizacji” opcjonalne


Używam SqlAlchemy na python3.4.3 do zarządzania moją bazą danych MySQL. Tworzyłem tabelę z:
from datetime import datetimefrom sqlalchemy import Column, text, create_engine
from sqlalchemy.types import TIMESTAMP
from sqlalchemy.dialects.mysql import BIGINT
from sqlalchemy.ext.declarative import declarative_baseBase = declarative_base()
class MyClass(Base): __tablename__ = 'my_class' id = Column(BIGINT(unsigned=True), primary_key=True)
created_at = Column(TIMESTAMP, default=datetime.utcnow, nullable=False)
updated_at = Column(TIMESTAMP, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
param1 = Column(BIGINT(unsigned=True), server_default=text('0'), nullable=False)

kiedy tworzę tę tabelę z:
engine = create_engine('{dialect}://{user}:{password}@{host}/{name}'.format(**utils.config['db']))
Base.metadata.create_all(engine)

Dostaję:
mysql> describe my_class;
+----------------+---------------------+------+-----+---------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------------------+-----------------------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| param1 | bigint(20) unsigned | NO | | 0 | |

Teraz problem polega na tym, że nie chcę, aby żaden serwer on_update ustawiał domyślnie mój atrybut
created_at
, jego przypisanie jest zasadniczo rejestrowane tylko podczas tworzenia rekordu, a nie przy każdej aktualizacji, jak określono w deklaracji klasy .
Z kilku przeprowadzonych przeze mnie testów zauważyłem, że jeśli wstawię inny atrybut, taki jak
TIMESTAMP
przed
created_at
, to ten atrybut zostanie dodatkowo
przy aktualizacji CURRENT_TIMESTAMP
, podczas gdy
created_at
nie robi tego tak, jak by chciał. Sugeruje to, że pierwszy atrybut
TIMESTAMP
SqlAlchemy znaleziony w deklaracji wyświetlania otrzymuje dodatkowy atrybut
przy aktualizacji CURRENT_TIMESTAMP
, chociaż nie widzę powodu takiego zachowania.
Ja też tego próbowałem:
created_at = Column(TIMESTAMP, default=datetime.utcnow, server_onupdate=None, nullable=False)

i
created_at = Column(TIMESTAMP, default=datetime.utcnow, server_onupdate=text(''), nullable=False)

ale problem pozostaje.
Masz jakieś pomysły?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Najwyraźniej problem nie dotyczy SqlAlchemy, ale bazowego silnika MySQL. Domyślnym zachowaniem jest ustawienie
przy aktualizacji CURRENT_TIMESTAMP
w pierwszej kolumnie TIMESTAMP tabeli.
To zachowanie jest opisane

tutaj
http://dev.mysql.com/doc/refma ... mp... Jak rozumiem, możliwym rozwiązaniem jest uruchomienie MySQL z flagą
--explicit_defaults_for_timestamp = FALSE
. Można znaleźć inne rozwiązanie

tutaj
https://stackoverflow.com/a/5126546... Nie próbowałem jeszcze żadnego rozwiązania, zaktualizuję tę odpowiedź, gdy tylko rozwiążę problem.
EDYCJA: próbowałem drugiej metody i nie jest to zbyt wygodne, ale działa. W moim przypadku utworzyłem zestaw tabel, które nie mają atrybutu
created_at
, a następnie zmieniłem wszystkie inne tabele, jak opisano w powyższym linku.
Coś w stylu:
_no_alter = set(['tables', 'which', 'do not', 'have', 'a created_at', 'column'])
Base.metadata.create_all(engine)
for table in Base.metadata.tables.keys():
if table not in _no_alter:
engine.execute(text('ALTER TABLE {} MODIFY created_at TIMESTAMP NOT NULL DEFAULT 0'.format(table)))

EDIT2: Innym (łatwiejszym) sposobem na to jest ustawienie w SqlAlchemy wartości
server_default
dla kolumny:
created_at = Column(TIMESTAMP, default=datetime.utcnow, nullable=False, server_default=text('0'))
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Napotkałem ten sam problem, możesz to zrobić za pomocą:
created_time = Column(TIMESTAMP, nullable=False, server_default=func.now())
updated_time = Column(TIMESTAMP, nullable=False, server_default=text('CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'))

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się