V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
gkiwi
V2EX  ›  Python

如何为 sqlalchemy 统一加表明前缀?

  •  
  •   gkiwi · 2014-08-19 11:57:40 +08:00 · 5921 次点击
    这是一个创建于 3748 天前的主题,其中的信息可能已经有所发展或是发生改变。
    酱紫:

    原先有表A,B,C等.也已经做好了AModel,BModel,CModel.
    现在因为需求原因(合并库),需要在A,B,C前面加前缀xxx,变成:
    xxx_A,xxx_B,xxx_C
    xxxAModel,xxxBModel,xxxCModel

    当然手动一个个改也可以,只是一个比较麻烦,二是调用时候,xxxAModel调用也会很难看.请问有啥解决方案没?

    网上搜到几个,但是不解决问题.

    求靠谱方案,谢谢.

    sqlalchemy版本:0.9.7

    9 条回复    2014-08-21 14:26:42 +08:00
    Zuckonit
        1
    Zuckonit  
       2014-08-19 13:09:54 +08:00
    xxx_A,xxx_B,xxx_C这个是表名?
    自定义__metaclass__

    ========================
    xxxAModel,xxxBModel,xxxCModel这个:
    xxxAModel = AModel
    xxxBModel = BModel
    xxxCModel = CModel
    beordle
        2
    beordle  
       2014-08-19 13:42:55 +08:00   ❤️ 1
    这样一定程度上能满足你的需求
    class Class(db.Model):
    __tablename__ = 'wl_class'
    id = db.Column('class_id', db.Integer, primary_key=True)
    name = db.Column('class_name', db.String(45), nullable=False, unique=True)
    products = db.relationship('Product', backref='wl_class', lazy='dynamic')

    def as_dict(self):
    return dict([(c, getattr(self, c)) for c in self.__dict__ if c in ('name', 'products')])
    我是觉得这样很方便,__metaclass__应该也可以, 但是注意一旦要用__new__, 因为我觉得__ init__ 的调用时机可能不一定可以
    siteshen
        3
    siteshen  
       2014-08-19 14:30:47 +08:00   ❤️ 1
    _table_prefix = 'v1_'

    class BaseModel(BaseModel):
    @declared_attr
    def __tablename__(cls):
    # simple CamelCase to under_score
    name = ''.join([('_' + ch.lower()) if ch.isupper() else ch
    for ch in cls.__name__]).strip('_')
    return _table_prefix + name

    __abstract__ = True
    __table_args__ = {
    'mysql_engine': 'InnoDB',
    'mysql_charset': 'utf8'
    }

    # tablename: v1_user_token
    class UserToken(BaseModel):
    id = Column(INTEGER(unsigned=True), primary_key=True)
    siteshen
        4
    siteshen  
       2014-08-19 14:32:49 +08:00   ❤️ 1
    上面是之前某次用的表明,除了增加 prefix 外,附加功能:CamelCase to under_score。
    bcxx
        5
    bcxx  
       2014-08-19 14:40:48 +08:00   ❤️ 1
    gkiwi
        6
    gkiwi  
    OP
       2014-08-19 21:26:04 +08:00
    @Zuckonit
    @beordle

    两位的应该都无法解决这个问题(或者是我没看懂).

    @siteshen 这个方法确实能够解决问题,而且__tablename__上面用装饰器也是我之前从未考虑过得.这样子统一引用_table_prefix也能够很方便的更改.但是其亮点也是其劣势,这样子的__tablename__意味着我需要拷贝多份(似乎BaseModel不能够被继承使用,之前我使用出过问题,最后只能用多继承来实现部分常用方法.但是这块我觉得也有可能是我的用法不对.)

    @bcxx 这个也是我在网上找到的一个解决方案,也是我最喜欢的.可惜用的时候不晓得哪里出错了.打算写个demo测试下.
    beordle
        7
    beordle  
       2014-08-19 22:27:27 +08:00
    @gkiwi

    @siteshen 的方法只是把BaseModel(BaseModel)增加了个动态属性啊 他下一句不是就是被继承了么?class UserToken(BaseModel) 为何说不能被继承呢
    gkiwi
        8
    gkiwi  
    OP
       2014-08-20 10:27:50 +08:00
    @beordle 我晓得你的意思,我也觉得这样子是合理的,但是用起来确实出现些问题,估计是我哪里写错了.以后有机会我再写个demo试试看.谢啦/
    siteshen
        9
    siteshen  
       2014-08-21 14:26:42 +08:00
    @beordle
    @gkiwi 的意思应该是要用继承的方式使用公共字段。这个需要特殊处理,告诉SQLAlchemy建立多个Column。摘取部分代码如下(至于declared_attr的意思,你可以去看看文档,我也不太清楚):
    http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#mixing-in-columns

    from sqlalchemy.ext.declarative import declared_attr

    class ReferenceAddressMixin(object):
    @declared_attr
    def address_id(cls):
    return Column(Integer, ForeignKey('address.id'))

    class User(ReferenceAddressMixin, Base):
    __tablename__ = 'user'
    id = Column(Integer, primary_key=True)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3029 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:56 · PVG 18:56 · LAX 02:56 · JFK 05:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.