是否可以在cerberus,Python中设置条件验证?

时间:2020-05-22 11:39:42

标签: python-3.x validation conditional-statements cerberus

我使用Python软件包cerberus来验证我的有效负载 这是我的问题:

仅当来自另一个架构的某个字段具有确切值时,我才需要设置一个必填字段。像这样:

#!/usr/bin/python

import sys, sqlite3

class sqlMerge(object):
    """Basic python script to merge data of 2 !!!IDENTICAL!!!! SQL tables"""

    def __init__(self, parent=None):
        super(sqlMerge, self).__init__()

        self.db_a = None
        self.db_b = None

    def loadTables(self, file_a, file_b):
        self.db_a = sqlite3.connect(file_a)
        self.db_b = sqlite3.connect(file_b)

        cursor_a = self.db_a.cursor()
        cursor_a.execute("SELECT name FROM sqlite_master WHERE type='table';")

        table_counter = 0
        print("SQL Tables available: \n===================================================\n")
        for table_item in cursor_a.fetchall():
            current_table = table_item[0]
            table_counter += 1
            print("-> " + current_table)
        print("\n===================================================\n")

        if table_counter == 1:
            table_to_merge = current_table
        else:
            table_to_merge = input("Table to Merge: ")

        return table_to_merge

    def merge(self, table_name):
        cursor_a = self.db_a.cursor()
        cursor_b = self.db_b.cursor()

        new_table_name = table_name + "_new"

        try:
            cursor_a.execute("CREATE TABLE IF NOT EXISTS " + new_table_name + " AS SELECT * FROM " + table_name)
            for row in cursor_b.execute("SELECT * FROM " + table_name):
                print(row)
                cursor_a.execute("INSERT INTO " + new_table_name + " VALUES" + str(row) +";")

            cursor_a.execute("DROP TABLE IF EXISTS " + table_name);
            cursor_a.execute("ALTER TABLE " + new_table_name + " RENAME TO " + table_name);
            self.db_a.commit()

            print("\n\nMerge Successful!\n")

        except sqlite3.OperationalError:
            print("ERROR!: Merge Failed")
            cursor_a.execute("DROP TABLE IF EXISTS " + new_table_name);

        finally:
            self.db_a.close()
            self.db_b.close()

        return

    def main(self):
        print("Please enter name of db file")
        file_name_a = input("File Name A:")
        file_name_b = input("File Name B:")

        table_name = self.loadTables(file_name_a, file_name_b)
        self.merge(table_name)

        return

if __name__ == '__main__':
    app = sqlMerge()
    app.main()

所以我的架构应如下所示:

    "key2": {
      "type": "string",
      "required": \\\ true if dict1.key1 == 'valueX' else false \\\
    }

有人知道方法,如何实现? 谢谢

3 个答案:

答案 0 :(得分:0)

我已阅读文档,但没有找到答案。 在您的示例中,我不确定它是否真的有效。此外,我认为依赖项的工作方式与我的示例不同。但是也许我错了。

子计划中的依赖项似乎不起作用。 您的示例返回错误消息:

from cerberus import Validator
schema = {"dict1": {
        "type": "dict",
        "schema": {
            "key1": {
                "type": "string",
                "required": True,
                "allowed": ["valueX"]
            }
        }
    },
    "dict2": {
        "type": "dict",
        "schema": {
            "key2": {  # required if dependency matches
                "type": "string",
                "dependencies": {
                    "dict1.key1": ["valueX"]
                }
            }
        }
    }
}
payload = {
    "dict1": {
                "key1": 'valueX'
            },
     "dict2": {
                "key2": 'some_value'
            }       
    }

validator = Validator(schema)
if validator(payload):
    print('Super!')
else:
    print(str(validator.errors))

有错误:

{'dict2': [{'key2': ["depends on these values: {'dict1.key1': ['valueX']}"]}]}

但是当我尝试为“ dict2”设置依赖项时它起作用了

schema = {"dict1": {
        "type": "dict",
        "schema": {
            "key1": {
                "type": "string",
                "required": True#,
                #"allowed": ["valueX"]
            }
        }
    },
    "dict2": {
        "type": "dict",
        "dependencies": {
                    "dict1.key1": "sms"
                },
        "schema": {
            "key2": {  # required if dependency matches
                "type": "string"
            }
        }
    }
}

如果我错了,请告诉我。该解决方案确实会对我有所帮助。 谢谢

答案 1 :(得分:0)

我也为此而苦苦挣扎,这是一个较短的示例,我希望可以使用依赖项来工作。我将其发布为答案(但社区Wiki),因为代码块在注释中往往看起来不太好。希望没关系,而不是创建一个单独的问题。

更短的示例

schema = {
    'field1': {
        'required': True
    }, 
    'field2': {
        'required': True,      
         'dependencies': {
             'field1': 'one'
         }
    }
}

>>> document = {'field1': 'two'}
>>> v.validate(document, schema)
False
>>> print(v.errors)

{'field2': ['required field']}

根据我的理解,如果字段1等于“一”,则需要执行make field2。

我的第二次尝试是不要求这样做:

schema = {
    'field1': {
        'required': True
    }, 
    'field2': {
        'required': False,      
         'dependencies': {
             'field1': 'one'
         }
    }
}

但这通过了测试:

>>> document = {'field1': 'one'}
>>> v.validate(document, schema)
True
>>> print(v.errors)

{}

仅当我尝试在“ field1”没有批准的值时在“ field2”中提供值时,它们才会失败:

>>> document = {'field1': 'two', 'field2': 'test'}
>>> v.validate(document, schema)
False
>>> print(v.errors)

{'field2': ["depends on these values: {'field1': 'one'}"]}

因此,我认为Cerberus不支持该用例,或者如果是,我还没有找到合适的组合。

答案 2 :(得分:-1)

大多数时候,您会在图书馆的文档中找到解决方案。
您要查找的是“ 依赖项”下的

可以在以下位置找到Cerberus文档和相应部分的链接:
https://docs.python-cerberus.org/en/stable/validation-rules.html#dependencies

在文档中说:


提供映射时,不仅必须存在所有依赖关系,而且还必须匹配它们的任何允许值。


还支持使用点符号声明对子文档字段的依赖性:


对于您的示例,它只是意味着,如果您的要求绑定到一个值,则该值必须与使用“允许”规则指定的任何值匹配。

如果您的要求已绑定到架构,则可以通过点符号指定该架构及其子模式。

适用于您的解决方案如下所示:

"dict1": {
    "type": "dict",
    "schema": {
        "key1": {
            "type": "string",
            "required": True,
            "allowed": ["valueX"]
        }
    }
},
"dict2": {
    "type": "dict",
    "schema": {
        "key2": {  # required if dependency matches
            "type": "string",
            "dependencies": {
                "dict1.key1": ["valueX"]
            }
        }
    }
}

当您完全不指定任何“允许”规则时,我不确定这是否也行得通,但我猜很可能会如此。