Деформировать межполевую проверку, не выделяя поле

Я следовал этому примеру, но немного изменил его, чтобы он подходил для моего проекта

Вот что у меня есть:

class AgentFormValidation(object):        

    def __init__(self, context, request):
        self.context = context
        self.request = request

    def __call__(self, form, value):
        number = value['identity_information']['number']
        print validateID(number)
        type = value['identity_information']['type']
        q = sqlahelper.get_session().query(Agents.id_number).filter(Agents.id_number == number).first()

        if type == "IDNumber":
            if not validateID(number):
                if q:
                    exc = colander.Invalid(form["identity_information"], "ID Number %s already exists in Database" % number)
                    exc.number = "ID Number already exists " 
                    raise exc
            else:
                exc = colander.Invalid(form["identity_information"], "ID Number %s is not a valid SA ID Number" % number)
                exc.number = "Invalid ID number" 
                raise exc
        elif type == "Passport":
            if q:
                exc = colander.Invalid(form["identity_information"], "Passport number %s already exists in Database" % number)
                exc.number = "Passport number already exists"
                raise exc


def gen_agent_schema_form(self):
        _but = ('create agent',) 
        _title = "Create Agent"
        if not self.context.__is_new__:
            _but = ('update agent',)
            _title = "Agent Details"
        deals = []
        if self.context.ou:
            deals = [(deal.id, str(deal)) for deal in self.context.ou[0].org_deals]

        schema = Agent(validator=AgentFormValidation(self.context, self.request), title=_title).bind(deals=deals)
        form = Form(schema, buttons=_but)
        return schema, form

Проверка работает нормально. Он просто не хочет выделять элемент.

Когда я заменяю:

exc.number = "ID Number already exists"

с участием

exc['number'] = "ID Number already exists"  

Он выделяет, но выделяет самый первый элемент формы, first_name, что также неверно.

Я чувствую, что упускаю что-то маленькое.

ОБНОВЛЕНИЕ

Поэтому я немного поиграл, когда делаю:

  exc = colander.Invalid(form, "ID Number %s already exists in Database" % number)
  exc["identity_information"] = "ID Number already exists " 
  raise exc

Я получаю окно с предупреждением (не предупреждение js) над правильным полем:

изображение того, что я получаю

Вместо этого мне нужно поле для выделения, как в примере выше.


person Renier    schedule 24.01.2014    source источник
comment
Почему голосование против?????????   -  person Renier    schedule 27.01.2014


Ответы (1)


В вашем пользовательском валидаторе вы всегда передаете форму в качестве первого параметра в colander.Invalid(). Таким образом, вы добавляете сообщения проверки в верхнюю часть формы, но не запускаете подсветку узлов/элементов схемы. Начните использовать простые валидаторы, работающие с одним узлом/элементом схемы.

exc = colander.Invalid(form["identity_information"], "ID Number %s already exists in Database" % number)

Во всяком случае, я не вижу четкого требования для межполевой проверки. Вместо применения сложного валидатора на основе классов к схеме агента вы можете использовать доступные валидаторы-дуршлаги или создавать собственные валидаторы на каждом узле схемы агента, таким образом делая валидаторы максимально простыми. Ваша текущая реализация валидатора заботится о слишком большом количестве вариантов использования.

Я предположил, что у вас есть два разных варианта использования — регистрация и какая-то другая задача, связанная с агентом. Изобретая разные схемы, я могу проводить проверку, специфичную для узлов схемы и варианта использования. Уникальность идентификатора может быть важна только при создании материалов с помощью формы добавления/создания, в форме обновления пользователи могут не иметь возможности изменять все эти значения, а ограниченный набор личной информации.

Основная идея заключается в том, чтобы обычно применять валидаторы узлов схемы для получения сообщений проверки на узлах схемы. В особых случаях применяются валидаторы уровня формы (регистрация агента).

Ваш вариант использования иллюстрирует область проверки формы. Класс, который проверяет входные данные формы на соответствие схемам и обрабатывает темы, связанные с сохраняемостью (уникальность первичного ключа), делает слишком много. Оба должны быть инкапсулированы, чтобы развиваться отдельно. Ваши бизнес-правила со временем изменятся, таблица базы данных всегда будет требовать уникальности для первичных ключей.

Схемы

import colander

class AgentRegistration(colander.Schema): 
    """schema for agent registration with email validation

    Note the form validator is invoked only if none of the individual field validators raise an error.
    """

    first_name = colander.SchemaNode(colander.String())
    number = colander.SchemaNode(colander.Integer(), validator=can_register_agent)
    email = colander.SchemaNode(colander.String(), validator=colander.Email())
    verify_email = colander.SchemaNode(colander.String(), validator=colander.Email())

    validator = verify_email_validator


class AgentDeals(colander.Schema):
    "schema for managing agent deals"
    first_name = colander.SchemaNode(colander.String())
    number = colander.SchemaNode(colander.Integer(), validator=validateID)
    email = colander.SchemaNode(colander.String(), validator=colander.Email())  

Валидаторы схемы

def agent_unique(node, value):
    "validate uniqueness of value in database table Agents"
    if sqlahelper.get_session().query(Agents.id_number).filter(Agents.id_number == value).first()
         raise Invalid(node,
                  'ID Number %r is already given to another agent. Please change it' % value)

def valid_SA_ID(node, value):
    "validates SA ID Number - just a copy of your requirement calling your custom function"
    if not validateID(value):
         raise Invalid(node,
                  'SA ID Number %r is not valid.' % value)

def can_register_agent(node, value):
    "ensure Agent ID Number is a valid and not already existing in database"
    valid_SA_ID(node, value)
    agent_unique(node, value)  

def verify_email_validator(form, values):
    """schema level validator with access to all values

    validates emails are same
    validation messages are displayed on top of form"""

    if values['email'] != values['verify_email']:
        raise colander.Invalid(form, 'Email values do not match.')

Форма

class AgentRegistrationView(object)

    def __init__(self, request):
        """Set some common variables needed for each view.
        """
        self.request = request
        self.context = request.context

    @view_config(route_name='add_agent', permission='admin', renderer='add_agent.mako')
    def add_agent(self):
        """return form to create new agents

        may be we do not need to bind any deals data here"""

        schema = AgentRegistration() 
        form = deform.Form(schema, action=self.request.route_url('add_agent'), buttons=('Add Agent','Cancel'))


class AgentDealsView(object)

    def __init__(self, request):
        """Set some common variables needed for each view.
        """
        self.request = request
        self.context = request.context


    def get_deals(self)
        """return deals to be bound to Agent Schema"""
        if self.context.ou:
            return [(deal.id, str(deal)) for deal in self.context.ou[0].org_deals]


    @view_config(route_name='edit_agent' permission='edit', renderer='edit_agent.mako')
    def edit_agent(self):

        # we bind deals data to form
        schema = AgentDeals().bind(deals=self.get_deals())
        form = deform.Form(schema, action=self.request.route_url('edit_agent'), buttons=('Save','Cancel'))

использованная литература

Кроме того, вас может заинтересовать ColanderAlchemy, но это добавляет еще один уровень абстракции. . На самом деле, я вам не рекомендую.

person Sascha Gottfried    schedule 27.01.2014
comment
Спасибо за ваш ответ. Не мне решать, что site-packages we use, I just code it :)` что касается вашего предложения, при запуске отладчика он работает, но я не вижу ничего, относящегося к моей проблеме. - person Renier; 28.01.2014
comment
Спасибо за помощь :) - person Renier; 29.01.2014