在插入数据联合模式之前验证参数字典

validating parameter dictionaries before insertion in datajoint schema

我们想在人们可以插入到架构之前强制执行参数检查,如下所示,但下面的代码不起作用。

有没有办法实现预插入参数检查?

@schema
class AutomaticCurationParameters(dj.Manual):
    definition = """
    auto_curation_params_name: varchar(200)   # name of this parameter set
    ---
    merge_params: blob   # dictionary of params to merge units
    label_params: blob   # dictionary params to label units
    """
    def insert1(key, **kwargs):
        # validate the labels and then insert
        #TODO: add validation for merge_params
        for metric in key['label_params']:
            if metric not in _metric_name_to_func:
                raise Exception(f'{metric} not in list of available metrics')
            comparison_list = key['label_params'][metric]
            if comparison_list[0] not in _comparison_to_function:
                raise Exception(f'{metric}: {comparison_list[0]} not in list of available comparisons')
            if type(comparison_list[1]) != int and type(comparison_list) != float:
                raise Exception(f'{metric}: {comparison_list[1]} not a number')
            for label in comparison_list[2]:
                if label not in valid_labels:
                  raise Exception(f'{metric}: {comparison_list[2]} not a valid label: {valid_labels}')               
        super().insert1(key, **kwargs)

这是一个很好的问题,我们已经多次提出这个问题。

问题很可能是您缺少 class' self 引用,或者您缺少 key 作为关键字参数传入的情况(我们实际上期望它是 row

我将演示一个简单示例,希望它可以说明如何注入您的验证代码,您可以调整验证代码以按照您上面的意图执行。

假设,我们想跟踪 dj.Manual table 中的文件路径,但我想验证是否只插入了具有特定扩展名的文件路径。

正如您已经发现的那样,我们可以像这样通过重载来实现这一点:

import datajoint as dj

schema = dj.Schema('rguzman_insert_validation')

@schema
class FilePath(dj.Manual):
    definition = '''
    file_id: int
    ---
    file_path: varchar(100)
    '''
    def insert1(self, *args, **kwargs):  # Notice that we need a reference to the class
        key = kwargs['row'] if 'row' in kwargs else args[0]  # Handles as arg or kwarg
        if '.md' not in key['file_path']:
            raise Exception('Sorry, we only support Markdown files...')
        super().insert1(*args, **kwargs)

P.S。尽管此示例旨在说明概念,但如果您使用 MySQL8,实际上还有更好的方法来执行上述操作。 MySQL 提供了一个 CHECK 实用程序,它允许 DataJoint 遵守的简单验证。如果满足这些条件,您可以将其简化为:

import datajoint as dj

schema = dj.Schema('rguzman_insert_validation')

@schema
class FilePath(dj.Manual):
    definition = '''
    file_id: int
    ---
    file_path: varchar(100) CHECK(REGEXP_LIKE(file_path, '^.*\.md$', 'c'))
    '''