2017-12-08 4 views
0

Ich bin dabei, Hosts zu migrieren, und die neuen Hosts verwendet eine neuere Version von MySQL, die strenger über das Format der Datetime-Werte ist, die es akzeptiert. Ich weiß, dass ich das ausschalten kann, aber ich würde gerne eine Lösung finden, um diese Werte korrekt in das richtige Format zu konvertieren. Vorzugsweise eine, die leicht über die vielen Modelle ausgetauscht werden kann, die ich aktualisieren muss (100 oder so).Format db.Datetime Werte automatisch in Flask-SQLAlchemy

Wenn ich keinen Weg finden kann, dies auf der Modellebene zu aktualisieren, muss ich möglicherweise die Tausenden von Standorten suchen, auf denen diese Werte festgelegt sind.

Ich habe ein Beispiel-Modell hier abgespeckte:

class Timesheet(BaseModel, db.Model): 
    __tablename__ = "timesheet" 
    timesheet_id = db.Column(db.Integer, primary_key=True) 
    created = db.Column(db.DateTime, default=datetime.utcnow) 
    updated = db.Column(db.DateTime) 
    employee_id = db.Column(db.Integer, db.ForeignKey('user.employee_id')) 
    description = db.Column(db.String(255)) 
    hours = db.Column(db.Numeric(9, 2)) 
    billable = db.Column(db.Boolean, default=False) 
    retainer = db.Column(db.Boolean, default=False) 
    client_id = db.Column(db.Integer, db.ForeignKey('client.client_id'), default=None) 
    project_id = db.Column(db.Integer, db.ForeignKey('project.project_id'), default=None) 
    task_id = db.Column(db.Integer, default=None) 
    timesheet_date = db.Column(db.DateTime, default=datetime.utcnow) 

Ich hoffe es eine Möglichkeit, db.Datetime zu ändern, so dass es eine wahre Python Datetime-Objekt zurückgibt, wenn sie mit einem ISO8601 Datetime-Saite ('YYYY-MM-DDT00: 00: 00.000Z')

der Suche nach etwas entlang der Linien von:

class FormattedDateTime(db.DateTime): 
    def self.__set__(self, value): 
     return dateutil.parser.parse(value) 

Die Spaltendefinition würde dann geändert werden:

updated = db.Column(FormattedDateTime) 

... so dass es automatisch mit dem richtigen Format speichert, wenn SQLAlchemy an MySQL sendet.

Ich habe mir Mixins angeschaut und nach Ansätzen gesucht, die das erreichen, aber ich finde keine guten Lösungen. Hilfe wird sehr geschätzt.

AKTUALISIERT: Dies ist ein Rohentwurf, was ich bisher gearbeitet ... es gut zu tun, auch scheint beim Filtern/auf dem Feld in einer Abfrage zu vergleichen, aber nicht gut getestet wird nur noch .

class TFDateTime(TypeDecorator): 
    impl = DATETIME 

    def process_bind_param(self, value, dialect): 
     if value is None: 
      return None 
     print("process_bind_param", value, type(value)) 
     if type(value) == datetime or type(value) == date: 
      return value 
     elif type(value) == str: 
      return parse(value, ignoretz=True) 
     else: 
      return None 

    def process_result_value(self, value, dialect): 
     if value is None: 
      return None 
     print("process_result_value", value, type(value)) 
     return value 

Antwort

1

Ich bin überrascht, ist die eingebaute in Datetime-Typ nicht automatisch einen gültigen Wert an die DB geben - es könnte ein Fehler in SQLAlchemy sein?

Das heißt, wird wahrscheinlich eine benutzerdefinierte Art zu schaffen, was Sie wollen - es gibt eine few examples in the SQLAlchemy docs, aber so etwas wie dies sollte Ihnen den Einstieg:

import datetime 
from sqlalchemy.types import TypeDecorator, TIMESTAMP 
import iso8601 

class ISO8601DateTime(TypeDecorator): 
    impl = TIMESTAMP 

    def process_bind_param(self, value, dialect): 
     if value is None: 
      return None 

     if isinstance(value, datetime.datetime): 
      return value.strftime(<iso8601-format-string>) 

     return value 

    def process_result_value(self, value, dialect): 
     if value is None: 
      return None 

     return iso8601.parse_date(value) 

Verwendet die iso8601 lib der Kürze halber date-util notwendig werden könnten. Möglicherweise müssen Sie auch dialektspezifische Typen für timestamp/datetime verwenden.

+0

Das ist wirklich nah an dem, was ich suche, obwohl ich nicht versuche, meinen Wert zu 8601 zu bekommen, nur wenn es ISO 8601 ist, sollte es korrekt zu einem Python Datetime-Objekt konvertieren, meine Frage mit bearbeiten was ich bisher erarbeitet habe ... – LegendaryJLD

Verwandte Themen