问题 #
sqlalchemy是一个class对应一张表,但是,如果我们有这样一个需求,分表的需求,此时,我们表结构一样,但是我们表名不一样, 这样的好处是,我们将很大的数据分成小的不同的表,使得我们有更好的查询速度和查询效率,但是问题就这么来了,我们该如何动态的 更新表名呢?最蠢得办法是也定义不同的class去映射相映的分表。不好,并不优雅
解决方案 #
- 我们动态的更新表名,只需要提前设置
__tablename__的属性即可,那么,我们怎么做呢?
- 首先,我们定义一个class去映射
class User(db.Model):
__tablename__ = 'User'
id = db.Column(db.Interger,primary_key=True)
user_name = db.Column(db.String(50))
-
然后我们每次调用他之前更改他的表名
User.__table__.name = 'user_1' -
这时我们就可以用这个User类去查询了
User.query.filter(User.id = 1).first()缺陷 #
然而不幸的是,这总方法查询是没问题,但是如果我们插入或者我们需要查询多张表的时候,他只能认第一次设置的表明,这就麻烦了 但是,依然是有解决方法的,而且更加的优雅!
终极解决方案 #
我们知道,python是动态语言,我们也知道,class也是一个对象,那么我们只要动态的创建一个class,再利用这个class去查询就可以 优雅的解决了。
-
首先,我们定义一个对象,并且让他能够动态的得到我们想要的表明的类,
class User(object): _mapper = {} @staticmethod def model(id): table_name = 'user_%s' %(id) ModelClass = User._mapper.get(class_name) if ModelClass is None: ModelClass = type(class_name,(db.Model,),{ '__module__' : __name__, '__name__' : class_name, '___tablename__':table_name, 'id' : db.Column(db.Integer, primary_key=True), 'user_name' : db.Column(db.String(50)), }) User._mapper[class_name] = ModelClass cls = ModelClass() return cls此时我们就可以用这个方法返回的类去查询和插入都可以
# 查询 user_model = User.model(1) user_model.query.filter(user_model.id = 1).one() # 插入 user_model.user_name = "赵四" db.session.add(user_model) db.session.commit