python, пн go и зефир: борьба за время и время - PullRequest
1 голос
/ 10 апреля 2020

Я пытаюсь сделать что-то довольно простое: получить текущее время, проверить мой объект с помощью зефира, сохранить его в пн go

python 3.7

требования:

datetime==4.3
marshmallow==3.5.1
pymongo==3.10.1

schema.py

from marshmallow import Schema, fields
...
class MySchema(Schema):
    user_id = fields.Str(required=True)
    user_name = fields.Str()
    date = fields.DateTime()
    account_type = fields.Str()
    object = fields.Raw()

preapredata.py

from datetime import datetime
from schema.py import Myschema
... 
        dt = datetime.now()
        x = dt.isoformat()
        data = {
            "user_id": '123123123',
            "user_name": 'my cool name',
            "date":  x,
            "account_type": 'another sting',
            "trade": {'some':'dict'}
        }
        # validate the schema for storage
        validator = MySchema().load(data)
        if 'errors' in validator:
            log.info('validator.errors')
            log.info(validator.errors)
...
        res = MyService().create(
            data
        )

myservice.py

    def create(self, data):
        log.info("in creating data service")
        log.info(data)

        self.repo.create(data)
        return MySchema().dump(data)

соединитель для пн go Хорошо, я сохраняю другие данные, у которых нет даты и времени, без проблем Кажется, я прошел через сотню различных вариантов форматирования даты и времени перед передачей его ключу даты, а также указал параметр «форматировать» в поле схемы как в строке, так и в метаклассе, например:

    #class Meta:
    #    datetimeformat = '%Y-%m-%dT%H:%M:%S+03:00'

Большинство вариантов, которые я пробую, приводят к:

{'date': ['Not a valid datetime.']}

Мне наконец-то удалось пройти проверку, используя просто

 x = dt.isoformat()

и оставив схему поля по умолчанию ( date = fields.DateTime ())

но когда я возвращаюсь обратно через зефир, я получаю

AttributeError: 'str' object has no attribute 'isoformat'

запись создается в пн go DB отлично, но тип поля - строка в идеале я хотел бы использовать поле даты

, имеющееся в поле mon * *1032*, если я попытаюсь передать

 datetime.now()

дате, она не будет выполнена с

{'date': ['Not a valid datetime.']}

то же самое для

datetime.utcnow()

Любое руководство действительно ценится.


Редактировать: при обходе зефира и использовании либо

datetime.now(pytz.utc)

, либо

datetime.utcnow() 

данных поля, хранящихся в пн go, как ожидается, как дата, поэтому вопрос, который я думаю, можно сформулировать более кратко, как: как я могу иметь поля зефира. DateTime () проверяет любой из этих форматов?


Редактировать 2: поэтому мы уже начали рефакторинг благодаря проницательному ответу Жерома ниже. для любого, кто хочет «скрутить» зефир, чтобы он вел себя так, как в первоначальном вопросе, мы в конечном итоге пошли: случай использования.

1 Ответ

1 голос
/ 11 апреля 2020

Смысл зефира заключается в загрузке данных из сериализованных (скажем, JSON, изоформатная строка и т. Д. c.) В реальные Python объекты (int, datetime, ...). И наоборот, чтобы вывести его из объекта в сериализованную строку.

Marshmallow также обеспечивает проверку при загрузке и только при загрузке. При выводе данных данные поступают из приложения и не должны проверяться.

В API полезно загружать и проверять данные из внешнего мира перед их использованием в приложении. И сериализовать его обратно во внешний мир.

Если ваши данные находятся в сериализованной форме, как в случае, когда вы вызываете isoformat () в вашем datetime, тогда зефир может загрузить его, и вы получите Python объект, с реальной датой в нем. Это то, что вы должны кормить pymon go.

    # load/validate the schema for storage
    try:
        loaded_data = MySchema().load(data)
    except ValidationError as exc:
        log.info('validator.errors')
        log.info(exc.errors)
    ...
    # Store object in database
    res = MyService().create(loaded_data)

Начиная с зефира 3, загрузка всегда возвращает десериализованный контент, и вам нужно попытаться / отловить ошибки проверки.

Если ваши данные не прийти к вашему приложению в десериализованной форме (если оно уже в форме объекта), тогда, возможно, зефир не является подходящим инструментом для работы, потому что он не выполняет проверку на десериализованных объектах (см. https://github.com/marshmallow-code/marshmallow/issues/1415) .

Или, может быть, это так. Вы можете использовать Object-Document Mapper (ODM) для управления проверкой и управлением базой данных. Это дополнительный слой другого пимона go. umon go - ODM mongoDB на основе зефира. Существуют и другие ODM: mongoengine, pymodm.

Кстати, что это за

datetime==4.3

Вы установили DateTime ? Вам это не нужно.

Отказ от ответственности: зефир и умон go говорит сопровождающий.

...