0

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

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

给定以下架构:

import colander

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

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

  • username尚未被其他用户使用
  • password并且confirmation是相同的

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

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'))

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

4

1 回答 1

1

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

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

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

检查密码匹配是另一回事,它不需要任何关于世界其他地方的知识,并且应该用滤锅相当简单。我不是滤锅专家,但看起来您可以使用延迟验证器来检查两个密码是否匹配。

关于您的代码的其他一些注释:

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