带有 SQLAlchemy 模型的 WTForms 中的唯一验证器 [英] Unique validator in WTForms with SQLAlchemy models

查看:37
本文介绍了带有 SQLAlchemy 模型的 WTForms 中的唯一验证器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个使用 SQLALchemy 管理数据库操作的应用程序中定义了一些 WTForms 表单.

I defined some WTForms forms in an application that uses SQLALchemy to manage database operations.

例如,用于管理类别的表单:

For example, a form for managing Categories:

class CategoryForm(Form):
    name = TextField(u'name', [validators.Required()])

这是相应的 SQLAlchemy 模型:

And here's the corresponding SQLAlchemy model:

class Category(Base):
    __tablename__= 'category'
    id = Column(Integer, primary_key=True)
    name = Column(Unicode(255))

    def __repr__(self):
        return '<Category %i>'% self.id

    def __unicode__(self):
        return self.name

我想在表单验证(而不是模型本身)上添加唯一约束.

I would like to add a unique constraint on the form validation (not on the model itself).

阅读 WTForms 文档,我发现了一个用一个简单的类来做到这一点:

Reading the WTForms documentation, I found a way to do it with a simple class:

class Unique(object):
    """ validator that checks field uniqueness """
    def __init__(self, model, field, message=None):
        self.model = model
        self.field = field
        if not message:
            message = u'this element already exists'
        self.message = message

    def __call__(self, form, field):         
        check = self.model.query.filter(self.field == field.data).first()
        if check:
            raise ValidationError(self.message)

现在我可以像这样将该验证器添加到 CategoryForm:

Now I can add that validator to the CategoryForm like this:

name = TextField(u'name', [validators.Required(), Unique(Category, Category.name)])

当用户尝试添加已存在的类别时,此检查效果很好 \o/但是当用户尝试更新现有类别(不更改名称属性)时,它将不起作用.

This check works great when the user tries to add a category that already exists \o/ BUT it won't work when the user tries to update an existing category (without changing the name attribute).

当您想要更新现有类别时:您将使用类别属性实例化表单以进行

When you want to update an existing category : you'll instantiate the form with the category attribute to edit:

def category_update(category_id):
    """ update the given category """
    category = Category.query.get(category_id)
    form = CategoryForm(request.form, category)

主要问题是我不知道如何访问验证器中现有的类别对象,这会让我从查询中排除编辑过的对象.

The main problem is I don't know how to access the existing category object in the validator which would let me exclude the edited object from the query.

有办法吗?谢谢.

推荐答案

在验证阶段,您将可以访问所有字段.所以这里的技巧是将主键传递到您的编辑表单中,例如

In the validation phase, you will have access to all the fields. So the trick here is to pass in the primary key into your edit form, e.g.

class CategoryEditForm(CategoryForm):
    id = IntegerField(widget=HiddenInput())

然后,在唯一验证器中,将 if 条件更改为:

Then, in the Unique validator, change the if-condition to:

check = self.model.query.filter(self.field == field.data).first()
if 'id' in form:
    id = form.id.data
else:
    id = None
if check and (id is None or id != check.id):

这篇关于带有 SQLAlchemy 模型的 WTForms 中的唯一验证器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆