flask-marshmallow: как пометить все поля как необязательные только тогда, когда метод PUT

Я делаю flask restful api, у меня проблемы с зефиром-sqlalchemy и webargs

короче, вот моя модель sqlalchemy:

class User(Model):
    id = Column(String, primary_key=True)
    name = Column(String(64), nullable=False)
    email = Column(String(120), nullable=False)
    password = Column(String(128))
    creation_date = Column(DateTime, default=datetime.utcnow)

а это моя схема

class UserSchema(ModelSchema):
    class Meta:
        model = User
        strict = True
        sqla_session = db.session

user_schema = UserSchema()

и пример моих маршрутов с использованием flask-classful и webargs:

class UserView(FlaskView):
    trailing_slash = False
    model = User
    schema = user_schema

    @use_kwargs(schema.fields)
    def post(self, **kwargs):
        try:
            entity = self.model()

            for d in kwargs:
                if kwargs[d] is not missing:
                    entity.__setattr__(d, kwargs[d])

            db.session.add(entity)
            db.session.commit()
            o = self.schema.dump(entity).data
            return jsonify({'{}'.format(self.model.__table__.name): o})

        except IntegrityError:
            return jsonify({'message': '{} exist in the database. choose another id'
                   .format(self.model.__table__.name)}), 409


    @use_kwargs(schema.fields)
    def put(self, id, **kwargs):
        entity = self.model.query.filter_by(id=id).first_or_404()

        for d in kwargs:
            if kwargs[d] is not missing:
                entity.__setattr__(d, kwargs[d])

        db.session.commit()
        o = self.schema.dump(entity).data
        return jsonify({'{}'.format(self.model.__table__.name): o})

UserView.register(app)

Проблема: как вы можете видеть в моей модели sqlalchemy, некоторые поля не могут принимать значения NULL, поэтому моя зефирная схема помечает их как обязательные. Все мои методы get, index, delete и post работают отлично. Но я включил пост по одной причине:

например, когда я пытаюсь опубликовать нового пользователя без имени, возникает HTTP-код 422, потому что требуется поле name, чего я и хочу, и это делается отлично.

НО при редактировании полей с запросом put я хочу, чтобы ВСЕ в моей схеме стало необязательным.. прямо сейчас, если я хочу обновить пользователя, я должен предоставить не только идентификатор.. но ВСЮ другую информацию, требуемую по умолчанию, даже если я этого не сделал менять их вообще.

Короче, как пометить все поля как «необязательные», когда метод «положен»?

EDIT: как и в случае с решением, предоставленным @Mekicha, я внес следующие изменения:

измените схему, чтобы обязательные поля в моей модели принимали значение None. как это:

class UserSchema(ModelSchema):
    class Meta:
        model = User
        ...
    name = fields.Str(missing=None, required=True)
    email = fields.Email(missing=None, required=True)
    ...

измените мое условие метода put и post с этого:

if kwargs[d] is not missing:

к этому:

if kwargs[d] is not missing and kwargs[d] is not None:

person RRR    schedule 18.05.2018    source источник
comment
Ознакомьтесь с документом по частичной загрузке.   -  person Mekicha    schedule 18.05.2018
comment
@Mekicha Я вроде понимаю, как использовать частичную загрузку. но как указать это в моем use_kwargs, чтобы ВСЕ поля были необязательными? Я попытался выполнить @use_kwargs(partial=True) и установить частичное значение для набора полей, но это не сработало :(   -  person RRR    schedule 20.05.2018
comment
пожалуйста, посмотрите мой ответ, если это может вам помочь   -  person Mekicha    schedule 20.05.2018
comment
Создайте экземпляр схемы с partial=True, например @use_kwargs(UserSchema(partial=True))   -  person andho    schedule 09.11.2018
comment
@andho Это действительно работает для вас или должно работать? Как и у ОП, у меня что-то вроде @use_kwargs(user_schema.fields), а не @use_kwargs(user_schema), и я не помню, почему. Но замена user_schema = UserSchema(strict=True) на user_schema = UserSchema(strict=True, partial=True) ничего не изменила. Я бы хотел использовать partial, а не указывать отдельные поля здесь и там.   -  person antgel    schedule 15.02.2019


Ответы (1)


Поскольку вы хотите сделать поля необязательными во время put, как насчет установки атрибута missing для полей. Из документа:

отсутствует используется для десериализации, если поле не найдено во входных данных

Я думаю, что это комбинация missing и allow_none (по умолчанию True, когда missing=None), как указано здесь: https://github.com/marshmallow-code/marshmallow/blob/dev/src/marshmallow/fields.py#L89 должен работать на вас

person Mekicha    schedule 20.05.2018