【问题标题】:How do you validate application logic using Pyramid's Colander?您如何使用 Pyramid 的漏勺验证应用程序逻辑?
【发布时间】:2017-07-29 23:48:43
【问题描述】:

到目前为止,我正在使用滤锅来验证我的 aiohttp 应用程序中的数据。

我面临的问题是我不知道如何进行“深度”验证。

给定以下架构:

import colander

class User(colander.MappingSchema):
    username = colander.SchemaNode(colander.String())
    password = colander.SchemaNode(colander.String())
    confirmation = colander.SchemaNode(colander.String())

我都验证了输入数据结构是否具有所有必需的字段(为了清楚起见,约束是最小的)但我也需要 检查:

  • username 尚未被其他用户占用
  • passwordconfirmation 是一样的

所以在我的控制器中,代码看起来像下面的伪代码:

def create_user(request):
    user = await request.json()
    schema = User()
    # do schema validation
    try:
        user = schema.deserialize(user)
    except colander.Invalid, exc:
        response = dict(
            status='error',
            errors=errors.asdict()
        )
        return json_response(response)
    else:
        # check password and confirmation are the same
        if user['password'] != user['confirmation']:
            response = dict(
                status='error'
                errors=dict(confirmation="doesn't match password")
            )
            return json_response(response)
        # check the user is not already used by another user
        # we want usernames to be unique
        if user_exists(user['user']):
            response = dict(
                status='error',
                errors=dict(username='Choose another username')
            )
            return json_response(response)

        return json_response(dict(status='ok'))

基本上有两种验证。是否可以在单个滤锅模式中同时拥有这两种逻辑?这是一个好的模式吗?

【问题讨论】:

    标签: python validation aiohttp colander


    【解决方案1】:

    显然这是一个品味问题,但恕我直言,最好将数据验证与应用程序逻辑分开。

    您在尝试确认用户名是否唯一时也会遇到一些问题:

    1. 滤锅需要了解您的应用程序,例如。获取对数据库连接的访问​​权限,以检查数据库是否存在该用户名。
    2. Colander (AFAIK) 未针对异步编程进行设置,因此在处理检查用户是否存在的 async 方法时会遇到问题。
    3. 您确实希望用户创建为 ACID,因此使用相同用户名同时调用 create_user 不可能创建具有相同用户名的两个用户。

    检查密码是否匹配是另一回事,它不需要任何关于世界其他地方的知识,并且对于漏勺来说应该是微不足道的。我不是滤锅专家,但看起来你可以使用deferred validator 来检查两个密码是否匹配。

    关于您的代码的其他一些说明:

    1. create_user 应该是 async 方法
    2. 我对您的数据库一无所知,但要从异步编程中获得任何优势user_exists 也应该是异步的
    3. 用户存在检查应包含在 ACID 用户创建中。例如。您应该使用 postgres 的 on conflict 或等效方法在创建重复用户时捕获它们,而不是先检查它们是否存在
    4. 为了保持适当的休息并使测试更容易,您的视图应该在出现错误时返回正确的 http 响应代码(目前所有状态都返回 200)。您应该使用 201 表示已创建,400 表示无效日期,409 或用户名冲突。

    【讨论】:

    • 发送!这段代码主要是伪代码,不是我正在运行的代码。我有一个关于第三点的问题。如果我将所有查询包装在一个事务中,它会提供与使用on conflict 相同的功能还是捕获重复用户?
    • 顺便说一句,我没有使用滤锅,而是使用更容易编写 IMO 的 traferet。
    • 看看 pydantic,更简单(虽然是我写的?)。事务可以做同样的事情,你应该设置用户名字段是唯一的,并处理冲突导致的错误。
    猜你喜欢
    • 1970-01-01
    • 2019-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 1970-01-01
    • 2015-11-10
    • 2016-09-06
    相关资源
    最近更新 更多