Проверка ограничения уникальности во время проверки формы в App Engine

Я использую Flask и WTforms в App Engine, пытаясь реализовать ограничение уникальности в одном из полей. Вопрос большой, пожалуйста, проявите терпение, и я застрял здесь много часов, мне нужна помощь от вас, люди. Месяц назад начал изучать App Engine, Flask и WTForms. Заранее спасибо.

Приложение имеет модель «Команда», как показано ниже:

class Team(db.Model):
    name = db.StringProperty(required=True)
    -- some other fields here --

Требование: Название команды должно быть уникальным.

Я перешел по ссылкам

Придумали следующий код:

models.py: создана отдельная таблица "Уникальные", как указано в ссылке:

class Unique(db.Model):

""" Handles uniqueness constriant on a field """

@classmethod
def unique_check(cls, form_name, field_data):
    def tx(form_name, field_data):
        key_name = "%s%s" % (form_name, field_data)
        uk = Unique.get_by_key_name(key_name)
        app.logger.debug("UK:" + str(uk))
        if uk:
            return False
        uk = Unique(key_name=key_name)
        uk.put()
        return True
    ret_val = db.run_in_transaction(tx, form_name, field_data)
    app.logger.debug("ret_val:" + str(ret_val))
    return ret_val

forms.py: я переопределил функции __init __ () и validate_on_submit (), в которых проверяется уникальность, и если она не уникальна, к этому полю добавляется ошибка, и ошибка проверки будет возникать так же, как и валидаторы wtforms.

class TeamForm(wtf.Form):

def __init__(self, *args, **kwargs):
    super(TeamForm, self).__init__(*args, **kwargs)
    if kwargs.get('edit', None):
        self.old_name = self.name.data.lower()

def validate_on_submit(self, edit=False):
    if not super(TeamForm, self).validate_on_submit():
        return False
    if edit:
        if self.old_name and self.old_name != self.name.data.lower():
            Unique.delete_entity(self.__class__.__name__, self.old_name)
            if not Unique.unique_check(self.__class__.__name__, self.name.data.lower()):
                self.name.errors.append("Value '%s' is not unique" % self.name.data)
        return False
    else:
        if not Unique.unique_check(self.__class__.__name__, self.name.data.lower()):
            self.name.errors.append("Value '%s' is not unique" % self.name.data)
            return False

    return True

    **----  Form fields declaration ----**

Приведенный выше код работает, когда вставлена ​​новая команда, я имею в виду, что он правильно проверяет уникальность. Проблема возникает, когда пользователь редактирует информацию о команде. Следующие два сценария проблематичны:

  • Когда пользователь пытается отправить форму, приложение выдаст ошибку «Не уникально», это очевидно, потому что в таблице «Уникальных» есть «key_name» для этой команды.
  • Если пользователь изменяет «название команды», приложение должно удалить предыдущее название команды из таблицы «Уникальных» и должно проверить уникальность для «измененного имени команды». Я не могу справиться с этими двумя сценариями.

Моя функция edit_team выглядит так:

@app.route('/team/edit/<key>', methods=['GET','POST'])
@login_required
def edit_team(key):

    k = db.Key(key)
    team = db.get(k)
    form = TeamForm(obj = team, edit=True) # to save old name, doesn't work.
    if form.validate_on_submit(edit=True): # edit=True is given only in edit function
        team.name = form.name.data
        -- others fields are updated in the similar way --
        team.put()
        return redirect(url_for('teams_list'))
    return render_template('edit_team.html', form=form)

Проблема может быть легко решена, если я смогу узнать «старое название» команды и удалить его из таблицы «Уникальные». Как видите, я сохраняю старое имя команды в функции TeamForm __init __ (), но __init __ () вызывается во время GET (старое имя сохраняется), а также в POST (измененное имя будет сохранено !!). Итак, я вообще не могу узнать старое название, и оно остается в таблице «Уникальные», никто больше не может использовать это «старое название команды».

Я попытался объяснить как можно больше, дайте мне знать, если вам нужна дополнительная информация.


person rajpy    schedule 08.05.2013    source источник
comment
возможный дубликат - stackoverflow.com/ questions / 5685831 /   -  person nsfyn55    schedule 01.06.2014
comment
возможный дубликат Как определить уникальное свойство для модели в Google App Engine?   -  person David Pope    schedule 01.06.2014


Ответы (1)


Изменить: не ответил на ваш вопрос правильно в первый раз.

Для запросов GET и POST будут созданы отдельные экземпляры объекта Form, поэтому вы не сможете сохранить old_name в self.

Вам нужно будет передать old_name браузеру в форме и попросить браузер отправить old_name обратно в запросе POST.

Самый простой способ сделать это - создать скрытое поле формы, которое пользователь не видит, но будет отправлено запросом POST. Я не слишком знаком с WTForms, но предполагаю, что вы можете инициализировать значение поля old_name в обработчике запроса GET.

person dragonx    schedule 08.05.2013
comment
Я хотел, чтобы он был уникальным. Я могу использовать название команды как key_name в сущности. Но у меня будет такая же проблема, как описано. Я хочу отображать ошибку проверки всякий раз, когда введенное пользователем имя команды присутствует в объекте Team (в данном случае). И такая же проблема возникает при редактировании.BTW, спасибо, что прочитали большой вопрос .. - person rajpy; 08.05.2013
comment
Даже я думал о таком же скрытом поле. Я буду смотреть в него. Если это невозможно, я сделаю название команды доступным только для чтения. - person rajpy; 08.05.2013
comment
Просто найдите HiddenField в документации: wtforms.simplecodes.com/docs/0.6/fields. html - person dragonx; 08.05.2013
comment
да .. мы можем создавать скрытые поля. Я подумал, что будет лучший способ сделать это. Чтобы сделать поле уникальным, нам нужно изменить HTML и models.py. Я хотел, чтобы это было как можно проще. - person rajpy; 08.05.2013