两个字段的组合在 Python Eve 中是唯一的

Combination of two fields to be unique in Python Eve

在 Python Eve 框架中,是否可以有一个条件来检查两个字段的组合是否唯一?

例如,下面的定义仅限制 firstnamelastname 对于资源中的项目是唯一的。

people = {
    # 'title' tag used in item links.
    'item_title': 'person',
    'schema': {
        'firstname': {
            'type': 'string',
            'required': True,
            'unique': True
        },
        'lastname': {
            'type': 'string',
            'required': True,
            'unique': True
        }
}

相反,有没有办法限制 firstnamelastname 的组合是唯一的?

或者有没有办法为此实现 CustomValidator?

您可能可以通过重载 _validate_unique 并在那里实现自定义逻辑来实现您想要的,利用 self.document 来检索其他字段值。

但是,由于每个唯一字段都会调用 _validate_unique,因此您最终会执行两次自定义验证,一次是 firstname,然后是 lastname。不是很理想。当然,最简单的方法是设置 fullname 字段,但我想这不是您的选择。

您是否考虑过采用稍微不同的设计?类似于:

{'name': {'first': 'John', 'last': 'Doe'}}

那么你只需要确保 name 是必需的 并且 是唯一的:

{
    'name': {
        'type':'dict', 
        'required': True, 
        'unique': True,
        'schema': {
            'first': {'type': 'string'},
            'last': {'type': 'string'}
        }
    }
}

灵感来自 Nicola 和 _validate_unique

from eve.io.mongo import Validator
from eve.utils import config
from flask import current_app as app

class ExtendedValidator(Validator):
    def _validate_unique_combination(self, unique_combination, field, value):
        """ {'type': 'list'} """
        self._is_combination_unique(unique_combination, field, value, {})


    def _is_combination_unique(self, unique_combination, field, value, query):
        """ Test if the value combination is unique.
        """
        if unique_combination:
            query = {k: self.document[k] for k in unique_combination}
            query[field] = value

            resource_config = config.DOMAIN[self.resource]

            # exclude soft deleted documents if applicable
            if resource_config['soft_delete']:
                query[config.DELETED] = {'$ne': True}

            if self.document_id:
                id_field = resource_config['id_field']
                query[id_field] = {'$ne': self.document_id}

            datasource, _, _, _ = app.data.datasource(self.resource)

            if app.data.driver.db[datasource].find_one(query):
                key_names = ', '.join([k for k in query])
                self._error(field, "value combination of '%s' is not unique" % key_names)