我在App Engine中使用Flask和WTforms,尝试在其中一个字段上实现唯一性约束。问题很大,请耐心等待,我已经被困在这里很多个小时,需要你们的帮助。一个月前开始学习App Engine,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:我重写了__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 ----**
以上代码在插入新团队时有效。我的意思是它会正确检查唯一性。当用户编辑团队信息时,会出现问题。以下两种情况存在问题:
我的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 __()函数中保存了团队的旧名称,但是在GET(保存旧名称)期间调用__init __()并且在POST中调用(修改后的名称将被保存!!)。所以,我根本找不到旧名称,它仍然在“唯一”表中,没有人可以使用这个“旧团队名称”。
我试图尽可能多地解释,如果你想了解更多信息,请告诉我。
答案 0 :(得分:1)
编辑:第一次没有正确回答你的问题。
将为GET和POST请求实例化Form对象的单独实例,因此您无法将old_name保存为self。
您需要将old_name传递给表单中的浏览器,并让浏览器在POST请求中提交old_name。
这样做的简单方法是创建一个用户看不到的隐藏表单字段,但将由POST请求提交。我对WTForms不太熟悉,但我假设您可以在GET请求处理程序中初始化old_name字段值。