sqlalchemy orm数据类型校验的几种方法
1.在定义ORM模型时校验
sqlalchemy提供validates函数支持对字段的校验
from sqlalchemy.orm import validates class EmailAddress(Base): __tablename__ = 'address' id = Column(Integer, primary_key=True) email = Column(String) @validates('email') def validate_email(self, key, address): assert '@' in address return address
2.全局校验
①.根据sqlalchemy数据类型对应的python_type(注:有些数据类型没有实现python_type这个方法,需重写)
在进行增改.commit()之前,对传入数据校验.字段的数据类型及是否为空可从已定义好的orm model中获取.
获取orm信息
@classmethod def orm_fields_info(cls): """ 从ORM中获取字段信息 :param cls:当前资源类 :type cls:类实例 :returns: 返回ORM字段类型,字段是否可空 """ fields_type = {} fields_nullable = {} orm_meta = cls.orm_meta for prop_name in orm_meta.__dict__: prop = getattr(orm_meta, prop_name) if isinstance(prop, attributes.InstrumentedAttribute): prop = prop.prop if isinstance(prop, properties.ColumnProperty): fields_type[prop_name] = prop.columns[0].type fields_nullable[prop_name] = prop.columns[0].nullable return fields_type, fields_nullable
根据orm 字段类型的python_type对传入的数据类型进行校验
def validate_data_type(orm_fields_info, field_name, field_value): fields_type, fields_nullable = orm_fields_info field_column = fields_type.get(field_name, None) if field_column: if not (not field_value and fields_nullable[field_name]): if hasattr(field_column, 'python_type'): if not isinstance(field_value, field_column.python_type): raise exceptions.ValidationError(attribute=field_name_display, msg=_( "field [%s] data type didn't match! require [%s],found type [%s]" % (field_name, field_column.python_type, type(field_value))))
②.利用sqlalchemy event创建通用校验器
from sqlalchemy import Column, Integer, String, DateTime from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import event import datetime Base= declarative_base() def validate_int(value): if isinstance(value, basestring): value = int(value) else: assert isinstance(value, int) return value def validate_string(value): assert isinstance(value, basestring) return value def validate_datetime(value): assert isinstance(value, datetime.datetime) return value validators = { Integer:validate_int, String:validate_string, DateTime:validate_datetime, } # this event is called whenever an attribute # on a class is instrumented @event.listens_for(Base, 'attribute_instrument') def configure_listener(class_, key, inst): if not hasattr(inst.property, 'columns'): return # this event is called whenever a "set" # occurs on that instrumented attribute @event.listens_for(inst, "set", retval=True) def set_(instance, value, oldvalue, initiator): validator = validators.get(inst.property.columns[0].type.__class__) if validator: return validator(value) else: return value class MyObject(Base): __tablename__ = 'mytable' id = Column(Integer, primary_key=True) svalue = Column(String) ivalue = Column(Integer) dvalue = Column(DateTime) m = MyObject() m.svalue = "ASdf" m.ivalue = "45" m.dvalue = "not a date"