Python 在应用程序引擎中检查表单验证期间的唯一性约束

Python 在应用程序引擎中检查表单验证期间的唯一性约束,python,google-app-engine,google-cloud-datastore,flask,wtforms,Python,Google App Engine,Google Cloud Datastore,Flask,Wtforms,我在AppEngine中使用Flask和WTforms,试图在其中一个字段上实现唯一性约束。问题很严重,请耐心点,我已经被困在这里好几个小时了,需要你们的帮助。一个月前开始学习应用程序引擎、Flask和WTForms。提前谢谢 应用程序具有如下所示的“团队”模型: class Team(db.Model): name = db.StringProperty(required=True) -- some other fields here -- 要求:团队名称必须是唯一的 我已经

我在AppEngine中使用Flask和WTforms,试图在其中一个字段上实现唯一性约束。问题很严重,请耐心点,我已经被困在这里好几个小时了,需要你们的帮助。一个月前开始学习应用程序引擎、Flask和WTForms。提前谢谢

应用程序具有如下所示的“团队”模型:

class Team(db.Model):
    name = db.StringProperty(required=True)
    -- some other fields here --
要求:团队名称必须是唯一的

我已经跟踪了链接

我们已经想出了以下代码:

models.py:创建了一个单独的表“Unique”,如链接中所示:

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:我已经重写了uuu init_uuuu()和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 ----**
上面的代码在插入新团队时有效。我的意思是它正确地检查了唯一性。当用户编辑团队信息时,会出现问题。以下两种情况存在问题:

  • 当用户试图提交表单时,应用程序将抛出“notunique”错误,这是显而易见的,因为“unique”表中有该团队的“key_name”
  • 如果用户更改“团队名称”,应用程序必须从“唯一”表中删除以前的团队名称,并且必须检查“更改的团队名称”的唯一性。我无法处理这两种情况
我的编辑团队功能如下所示:

@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)
@app.route('/team/edit/',方法=['GET','POST'])
@需要登录
def编辑团队(关键):
k=分贝键(键)
team=db.get(k)
form=TeamForm(obj=team,edit=True)#要保存旧名称,不起作用。
如果表单.validate_on_submit(edit=True):#edit=True仅在编辑功能中给出
team.name=form.name.data
--其他字段以类似方式更新--
团队。put()
返回重定向(url\u for('teams\u list'))
返回渲染模板('edit\u team.html',form=form)
如果我能够找到团队的“旧名称”,这样我就可以从“Unique”表中删除它,这个问题就可以很容易地解决。正如您所看到的,我正在TeamForm _uinit _;()函数中保存团队的旧名称,但是_init _;()在GET期间被调用(旧名称被保存),也在POST中被调用(修改后的名称将被保存!!)。所以,我根本找不到旧名称,它仍然保留在“唯一”表中,没有人可以再使用这个“旧团队名称”


我试着尽可能多地解释,如果您想了解更多信息,请告诉我。

编辑:第一次没有正确回答您的问题

表单对象的单独实例将为GET和POST请求实例化,因此不能将旧的_名称保存到self

您需要在表单中将旧的_名称传递给浏览器,并让浏览器在POST请求中重新提交旧的_名称


最简单的方法是创建一个隐藏的表单字段,用户看不到,但会通过POST请求提交。我不太熟悉WTForms,但我假设您可以在GET请求处理程序中初始化旧的_name字段值

是的,我希望它是独一无二的。我可以使用团队名称作为实体中的“密钥名称”。但是,我将遇到与前面解释的相同的问题。每当用户输入的团队名称出现在团队实体中时(在本例中),我希望显示“验证错误”。同样的问题在编辑时也会出现。顺便说一句,谢谢你阅读了这个大问题。甚至我也想到了同样的隐藏字段。我会调查的。如果不可能,我会将团队名称设置为只读。只需在文档中搜索HiddenField:是的。。我们可以创建隐藏字段。我在想会有更好的办法。为了创建唯一的字段,我们必须更改HTML和models.py。我希望它尽可能简单