【问题标题】:Web2py Field value depends on another field - (validate while defining the model)Web2py 字段值取决于另一个字段 - (在定义模型时验证)
【发布时间】:2017-02-22 13:29:37
【问题描述】:

请考虑下表:

db.define_table('bio_data',
            Field('name', 'string'),
            Field('total_mark', 'integer', requires=IS_EMPTY_OR(IS_INT_IN_RANGE(0, 1e100))),
            Field('marks_obtained', 'integer')
            )

现在“marks_obtained”字段的值不能大于“total_marks”。

我已经尝试了以下

db.bio_data.marks_obtained.requires = IS_EMPTY_OR(
IS_INT_IN_RANGE(0, db.bio_data.total_mark))

但这不起作用。我收到以下错误:

TypeError: int() argument must be a string or a number, not 'Field'

非常感谢任何帮助。

【问题讨论】:

  • 想办法得到Field的整数值。
  • 是的,这就是这里的问题,我怎样才能得到一个值而不是一个字段。我尝试了以下方法,但仍然出现错误:Field('marks_obtained', 'integer', requires=lambda row: IS_EMPTY_OR(IS_INT_IN_RANGE(0, db.bio_data(row.id).total_mark))) 并请求您在不了解完整问题或知识的情况下不要投反对票。
  • 你能输入dir(db.bio_data.total_mark) 看看它会返回什么吗?你有没有试过int(db.bio_data.total_mark)
  • int(db.bio_data.total_mark) 这给出了同样的错误,因为这个查询是 db.bio_data.total_mark 正在返回一个字段,而不是一个整数。

标签: python web2py data-access-layer


【解决方案1】:

我遇到了同样的问题,我刚刚找到了一个优雅的解决方案。首先,您需要注意,在任何验证之前,字段的值都会传输到模型,因此,在模型中,您可以通过 request.vars 操作它们。之后一切都很简单:只需创建自己的验证器,提取字段的值并根据需要使用它们。举个例子会更好:

假设您有一个包含两个字段的表:

    dbOBJECT.define_table("example",
                          Field("high_number",
                                "integer",
                                label= T('High number'),
                                requires=[IS_NOT_EMPTY(T(stringBuilder.emptyField))]),
                          Field("other_number",
                                "integer",
                                label= T('Lower number'),
                                requires=IS_NOT_EMPTY(T(stringBuilder.emptyField))))

并且您需要第二个数字小于第一个数字。出于解释的目的,让我们创建一个自定义验证器。这可以在同一个 db.py 文件中完成

    class VALIDATE_NUMBERS(object):
        def __init__(self, error_message="Error, this value can't be greather than the above one"):
            self.error_message = error_message

        def __call__(self, value):
            error = None
            high_number=request.vars['high_number']

            if high_number < value:
                error = self.error_message
            return (value, error)

嗯,另一件事是在模型中包含这个验证:

    dbOBJECT.define_table("example",
                          Field("high_number",
                                "integer",
                                label= T('High number'),
                                requires=[IS_NOT_EMPTY(T(stringBuilder.emptyField))]),
                          Field("other_number",
                                "integer",
                                label= T('Lower number'),
                                requires=IS_NOT_EMPTY [(T(stringBuilder.emptyField)), VALIDATE_NUMBERS()]))

魔法完成了!!!享受...

【讨论】:

    【解决方案2】:

    您可以使用onvalidation 回调函数轻松完成此操作。读这个 Form and validators - onvalidation

    第二个解决方案是你需要结合'Validators with dependencies'和IS_EXPR验证器。阅读:

    1. Validators with dependencies

    2. IS_EXPR

    controller 中添加验证器,如下所示,我尚未对此进行测试,但您会从中得到想法。

    is_total_less = int(request.vars.marks_obtained) < int(request.vars.total_mark)
    
    db.bio_data.marks_obtained.requires = IS_EMPTY_OR(
    IS_EXPR('%s' % is_total_less,
            error_message='Marks Obtained should be smaller than Totak Marks'))
    

    确保request.vars 可用。

    【讨论】:

    • 我已经能够使用onvalidation 回调来做到这一点。对于模型级别,我将尝试相同并更新。感谢您的更新。
    猜你喜欢
    • 2017-02-28
    • 2020-06-23
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-06
    • 2019-02-05
    • 1970-01-01
    相关资源
    最近更新 更多