SQLAlchemy学习-10. validates()校验器

前言

向属性添加“验证”的一种快速方法是使用 validates()装饰器。

校验器

属性验证器可以引发异常,停止改变属性值的过程,或者可以将给定值更改为不同的值。
与所有属性扩展一样,验证器仅由普通用户代码调用;当 ORM 填充对象时,它们不会发出。

from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.orm import validates


# 拼接配置dialect + driver://username:passwor@host:port/database
DB_URI = 'mysql+pymysql://root:123456@localhost:3306/web'
Base = declarative_base()


class EmailAddress(Base):
    __tablename__ = 'address'

    id = Column(Integer, primary_key=True)
    email = Column(String(50))

    @validates('email')
    def validate_email(self, key, address):
        if '@' not in address:
            raise ValueError("failed simple email validation")
        return address


if __name__ == '__main__':
    engine = create_engine(DB_URI)
    Base.metadata.create_all(engine)  # 将模型映射到数据库中

如果属性是关联另外一张表也可以验证

from sqlalchemy.orm import validates


class User(Base):
    __tablename__ = 'user'
    # ...
    id = Column(Integer, primary_key=True)
    addresses = relationship("Address")

    @validates('addresses')
    def validate_address(self, key, address):
        if '@' not in address.email:
            raise ValueError("failed simplified email validation")
        return address

默认情况下,不会为集合删除事件发出验证函数,因为典型的期望是被丢弃的值不需要验证。
但是,validates()通过指定include_removes=True给装饰器来支持接收这些事件。
设置此标志时,验证函数必须接收一个额外的布尔参数,如果该参数True指示该操作是删除:

from sqlalchemy.orm import validates

class User(Base):
    __tablename__ = 'user'
    # ...

    addresses = relationship("Address")

    @validates('addresses', include_removes=True)
    def validate_address(self, key, address, is_remove):
        if is_remove:
            raise ValueError(
                    "not allowed to remove items from the collection")
        else:
            if '@' not in address.email:
                raise ValueError("failed simplified email validation")
            return address

也可以使用选项定制相互依赖的验证器通过 backref 链接的情况include_backrefs=False;此选项设置为 时False,如果事件是由于反向引用而发生的,则防止发出验证函数:

from sqlalchemy.orm import validates

class User(Base):
    __tablename__ = 'user'
    # ...

    addresses = relationship("Address", backref='user')

    @validates('addresses', include_backrefs=False)
    def validate_address(self, key, address):
        if '@' not in address:
            raise ValueError("failed simplified email validation")
        return address

上面,如果我们要Address.user像 in 一样赋值,即使发生了追加,该函数也不会被发出- 该事件是由 backref 引起的。some_address.user = some_uservalidate_address()some_user.addresses

请注意,validates()装饰器是建立在属性事件之上的便利功能。需要对属性更改行为的配置进行更多控制的应用程序可以使用此系统,如AttributeEvents.

对象名称 描述
验证(*names, **kw) 将方法装饰为一个或多个命名属性的“验证器”。

将方法装饰为一个或多个命名属性的“验证器”。

将方法指定为验证器,该方法接收属性名称以及要分配的值,或者在集合的情况下,将值添加到集合中。然后,该函数可以引发验证异常以停止进程继续进行(其中 Python 的内置ValueError 和AssertionError异常是合理的选择),或者可以在继续之前修改或替换该值。否则,该函数应返回给定值。

请注意,集合的验证器不能在验证例程中发出该集合的负载 - 这种用法会引发断言以避免递归溢出。这是不支持的可重入条件。
参数:

  • *names - 要验证的属性名称列表。
  • include_removes - 如果为真,“删除”事件也将被发送 - 验证函数必须接受一个额外的参数“is_remove”,这将是一个布尔值。
  • include_backrefs -默认为True; if False,如果发起者是通过 backref 相关的属性事件,则不会发出验证函数。这可用于双向 validates()使用,每个属性操作只应发出一个验证器。
posted @ 2022-08-20 17:05  上海-悠悠  阅读(264)  评论(0编辑  收藏  举报