Можно ли проверить список с помощью зефира?

Можно ли проверить список с помощью зефира?

class SimpleListInput(Schema):
    items = fields.List(fields.String(), required=True)

# expected invalid type error
data, errors = SimpleListInput().load({'some': 'value'})

# should be ok 
data, errors = SimpleListInput().load(['some', 'value'])

Или ожидается проверка только объектов?


person avasin    schedule 15.05.2016    source источник
comment
Проблема может заключаться в том, что перебор словаря действительно дает строки; что, если вы передадите словарь, чьи ключи, например. целые числа?   -  person jonrsharpe    schedule 15.05.2016
comment
Вы проверяете значение errors? Когда я пробую ваш пример, кажется, что для него установлено соответствующее значение.   -  person larsks    schedule 15.05.2016


Ответы (3)


Чтобы проверить списки верхнего уровня, вам необходимо создать экземпляр схемы элемента списка с аргументом many=True.

Пример:

class UserSchema(marshmallow.Schema):
    name = marshmallow.fields.String()

data, errors = UserSchema(many=True).load([
    {'name': 'John Doe'},
    {'name': 'Jane Doe'}
])

Но это все равно должна быть объектная схема, Marshmallow не поддерживает использование необъектных списков верхнего уровня. В случае, если вам нужно проверить список необъектных типов верхнего уровня, обходным путем может быть определение схемы с одним полем списка ваших типов и просто перенос полезной нагрузки, как если бы это был объект:

class SimpleListInput(marshmallow.Schema):
    items = marshmallow.fields.List(marshmallow.fields.String(), required=True)

payload = ['foo', 'bar']
data, errors = SimpleListInput().load({'items': payload})
person Maxim Kulkin    schedule 01.12.2016

SimpleListInput — это класс с элементами свойств. Элементы свойства — это кто принимает список строк.

>>> data, errors = SimpleListInput().load({'items':['some', 'value']})
>>> print data, errors
{'items': [u'some', u'value']} 
{}
>>> data, errors = SimpleListInput().load({'items':[]})
>>> print data, errors
{'items': []} 
{}
>>> data, errors = SimpleListInput().load({})
>>> print data, errors
{} 
{'items': [u'Missing data for required field.']}

Если вы хотите пользовательскую проверку, например, не принимать пустой список в элементах:

from marshmallow import fields, Schema, validates, ValidationError

class SimpleListInput(Schema):
    items = fields.List(fields.String(), required=True)

    @validates('items')
    def validate_length(self, value):
        if len(value) < 1:
            raise ValidationError('Quantity must be greater than 0.') 

Затем...

>>> data, errors = SimpleListInput().load({'items':[]})
>>> print data, errors
{'items': []} 
{'items': ['Quantity must be greater than 0.']}

Взгляните на Проверка.

ОБНОВЛЕНИЕ:

Как @Turn прокомментировал ниже. Ты можешь это сделать:

from marshmallow import fields, Schema, validate

class SimpleListInput(Schema):        
    items = fields.List(fields.String(), required=True, validate=validate.Length(min=1))
person Jair Perrut    schedule 29.09.2016
comment
Для этого вам не нужен собственный валидатор: items = fields.List(fields.String(), required=True, validates=Length(min=1)) - person Turn; 10.05.2018
comment
Нельзя редактировать менее 6 символов. Правильный фрагмент validate=Length(min=1) - person Alwx; 07.04.2020

Пожалуйста, взгляните на небольшую библиотеку, написанную мной, которая пытается решить именно эту проблему: https://github.com/and-semakin/marshmallow-toplevel.

Монтаж:

pip install marshmallow-toplevel

Использование (на примере Максима Кулькина):

import marshmallow
from marshmallow_toplevel import TopLevelSchema

class SimpleListInput(TopLevelSchema):
    _toplevel = marshmallow.fields.List(
        marshmallow.fields.String(),
        required=True,
        validate=marshmallow.validate.Length(1, 10)
    )

# raises ValidationError, because:
# Length must be between 1 and 10.
SimpleListInput().load([])

# raises ValidationError, because:
# Length must be between 1 and 10.
SimpleListInput().load(["qwe" for _ in range(11)])

# successfully loads data
payload = ["foo", "bar"]
data = SimpleListInput().load(payload)
assert data == ["foo", "bar"]

Конечно, его можно использовать с более сложными схемами, чем просто строка в примере.

person Andrey Semakin    schedule 25.12.2019