Gar*_*rwe 19 python sqlalchemy
我有一个sqlalchemy模型,其中所有表格/对象都有一个注释字段.因此,为了尝试遵循DRY原则,我将该字段移至mixin类.
class NotesMixin(object):
notes = sa.Column(sa.String(4000) , nullable=False, default='')
class Service(Base, NotesMixin):
__tablename__ = "service"
service_id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(255), nullable=False, index=True, unique=True)
class Datacenter(Base, NotesMixin):
__tablename__ = "datacenter"
datacenter_id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(255), nullable=False, index=True, unique=True)
class Network(Base, NotesMixin, StatusMixin):
__tablename__ = "network"
network_id = sa.Column(sa.Integer, primary_key=True)
etc...
Run Code Online (Sandbox Code Playgroud)
现在notes列是model/db中的第一列.我知道这不会影响我的应用程序的功能,但是在ID之前看到笔记会让我感到恼火等等.有什么方法可以将它移到最后?
Ste*_*ven 23
找到更清洁的解决方案
sqlalchemy.ext.declarative.declared_attr在sqlalchemy 0.6.5中使用装饰器(sqlalchemy sqlalchemy.util.classproperty<= 0.6.4)
class NotesMixin(object):
@declared_attr
def notes(cls):
return sa.Column(sa.String(4000) , nullable=False, default='')
Run Code Online (Sandbox Code Playgroud)
根据文档,这是"对于具有外键的列,以及需要目标显式上下文的各种映射器级构造".虽然严格来说这不是这里的情况,但它是通过在构造子类时调用方法(并创建列)来实现的,因此无需进行复制.这意味着mixin专栏将在最后出现.可能是一个比黑客更好的解决方案_creation_order......
答案很简单:只需自己创建数据库表,而不是使用sqlalchemy metadata.create_all().
如果您没有找到可接受的,我担心这本身需要(小)更改sqlalchemy.ext.declarative,或者您必须创建自己的元类并declarative_base()使用metaclass关键字参数传递给它.然后将使用该类而不是默认值DeclarativeMeta.
说明:sqlalchemy使用列属性的创建顺序,它存储在"private"属性中._creation_order(在调用Column()时生成).声明性扩展通过从mixin类创建列对象的副本并将其添加到类中来混合列.在._creation_order这个副本中设置为相同的值mixin类的原始属性.由于mixin类当然是首先创建的,因此它的列属性将具有比子类更低的创建顺序.
因此,为了使您的请求成为可能,应在制作副本时分配新的创建顺序,而不是采用原始顺序.你可以尝试根据这个解释制作自己的元类,并使用它.但您也可以尝试询问sqlalchemy开发人员.也许他们愿意接受这个作为错误/功能请求?至少,它看起来像是一个小的(一线)改变,除了你要求的改变之外没有任何影响(这可能更好).
我迟到了这个问题,但作为参考,如果您使用 SA 2.0,只需将 sort_order 传递给mapped_column,例如:
class NotesMixin:
note = mapped_column(String(255), sort_order=999)
Run Code Online (Sandbox Code Playgroud)
还可以在 CREATE TABLE 编译时更改列的顺序(此处以postgresql方言为例):
from sqlalchemy.schema import CreateTable
from sqlalchemy.ext.compiler import compiles
@compiles(CreateTable, 'postgresql')
def _compile_create_table(element, compiler, **kwargs):
element.columns = element.columns[::-1] # reverse order of columns
return compiler.visit_create_table(element)
Run Code Online (Sandbox Code Playgroud)
然后这可以与metadata.create_all().
| 归档时间: |
|
| 查看次数: |
3154 次 |
| 最近记录: |