如何使用Pyramid的漏勺验证应用程序逻辑?

时间:2017-07-22 08:50:58

标签: python validation aiohttp colander

到目前为止,我正在使用漏勺来验证我的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'))

基本上有两种验证方式。是否可以在单个漏勺模式中使用两个逻辑?这是一个好的模式吗?

1 个答案:

答案 0 :(得分:1)

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

尝试确认用户名是唯一的时,您还会遇到一些问题:

  1. 漏勺需要了解您的应用,例如。访问数据库连接以检查数据库是否存在该用户名。
  2. 没有为asyncio编程设置漏勺(AFAIK),因此在处理检查用户存在的async方法时会遇到问题。
  3. 您确实希望将用户创建设置为ACID,因此使用相同用户名同时调用create_user无法创建具有相同用户名的两个用户。
  4. 检查密码匹配是另一个故事,它不需要任何关于世界其他地方的知识,并且应该用漏勺相当微不足道。我不是漏勺的专家,但看起来你可以使用deferred validator检查两个密码匹配。

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

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