Как добавить проверку на уровне формы в класс Flatland Form? - PullRequest
0 голосов
/ 03 декабря 2010

У меня есть форма flatland для прокси-сайта, которая выглядит примерно так:

class doSomethingForm(Form):
  '''Do an action with account credentials'''
  username = String.using(default='',
    validators=[Present(), UsernameFormat()])
  password = String.using(default='',
    validators=[Present(), PasswordFormat()])
  action = String.using(default='',
    validators=[Present(), ActionFormat()])

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

Это очень похоже на проверку на уровне контейнера flatland, которая сначала выполняет проверку для содержащихся элементов.Итак, я попробовал это:

class doSomethingForm(Form):
  '''Do an action with account credentials'''
  account = Dict.of(
    username = String.named('username').using(default='',
      validators=[Present(), UsernameFormat()])
    password = String.named('password').using(default='',
      validators=[Present(), PasswordFormat()])
  ).using(validators=[CheckCredentials()])
  action = String.using(default='',
    validators=[Present(), ActionFormat()])

Похоже, это будет работать, но теперь форма ищет элементы с именами account_username и account_password, что не совсем тот интерфейс, на который я надеялся.

Я вижу пару решений:

  1. Я мог бы присоединить валидатор CheckCredentials к doSomethingForm.Но я не вижу способа сделать это в документации.
  2. Я мог бы присоединить валидатор CheckCredentials к username, который может получить доступ к своему брату password.Однако я не хочу беспокоить другой сервер, если имя пользователя и пароль имеют неверный формат.поэтому мне сначала нужно было выполнить проверки на username и password, что похоже на повторение.
  3. Я мог бы взломать версию Dict, которая не делает пространства имен

Есть ли правильный способ добавить валидаторы уровня формы в равнине?

Ответы [ 2 ]

1 голос
/ 03 декабря 2010

Полезно проверить код равнинной местности (hg clone http://bitbucket.org/jek/flatland), потому что документация и примеры еще не совсем там.

Form наследуется от Dict, который наследуется от Container, который наследуется от Element.Есть два элемента класса, которые помогут:

  • descent_validators (из Container) - итерация валидаторов для запуска на первой (первой) фазе спуска.
  • validators (из Element) - итератор Validators для запуска на второй (второй) фазе подъема.

Чтобы получить желаемое поведение (проверьте учетную запись, только еслиимя пользователя и пароль действительны), мне нужно добавить свой валидатор в переменную класса validators и проверить, что дочерние валидаторы прошли.

Мой код теперь выглядит примерно так:

class CheckCredentials(Validator):
  '''Checks credentials and creates an account object'''

  def validate(self, element, state):
    username = element['username']
    password = element['password']
    if not (username.all_valid and password.all_valid):
      return false

    self.account = Account(username.u, password.u)
    return self.account.valid()


class doSomethingForm(Form):
  '''Do an action with account credentials'''
  username = String.using(default='',
    validators=[Present(), UsernameFormat()])
  password = String.using(default='',
    validators=[Present(), PasswordFormat()])
  action = String.using(default='',
    validators=[Present(), ActionFormat()])

  validators = (CheckCredentials(),)

@expose('/do_something')
def doSomething(request):
  form = doSomethingForm.from_defaults()
  form.set_flat(request.form)

  result_html = ''
  method = request.method
  if method == 'POST' and not form.validate():
    method = 'GET'
    errors = []
    if form.errors: errors.extend(form.errors)
    for el in form.all_children:
      if el.errors: errors.extend(el.errors)
    result_html = errorsToHtml(errors)

  if method == 'POST':
    result_html = form.account.action(form['action'].u)

  return render_template('do_something.html',
    result=result_html, **form.value)

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

Благодаря WoLpH и jek за помощь.

1 голос
/ 03 декабря 2010

После прочтения небольшого количества документов я могу предположить, что вы можете просто сделать your_form.validate().

Класс Form наследует класс Dict, поэтому способ проверки может быть идентичен тому, как обычно работает проверка на уровне контейнера.

Отказ от ответственности: до твоего вопроса я никогда не слышал о "равнине", поэтому я действительно могу быть здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...