SQLAlchemy: avoiding repetition in declarative style class definition

后端 未结 3 623
谎友^
谎友^ 2021-02-05 21:48

I\'m using SQLAlchemy, and many classes in my object model have the same two attributes: id and (integer & primary key), and name (a string). I\'m trying to avoid declaring

相关标签:
3条回答
  • 2021-02-05 22:29

    I think I got it to work.

    I created a metaclass that derives from DeclarativeMeta, and made that the metaclass of C1 and C2. In that new metaclass, I simply said

    def __new__(mcs, name, base, attr):
      attr['__tablename__'] = name.lower()
      attr['id'] = Column(Integer, primary_key = True)
      attr['name'] = Column(String)
      return super().__new__(mcs, name, base, attr)
    

    And it seems to work fine.

    0 讨论(0)
  • 2021-02-05 22:53

    You could factor out your common attributes into a mixin class, and multiply inherit it alongside declarative_base():

    from sqlalchemy import Column, Integer, String
    from sqlalchemy.ext.declarative import declarative_base
    
    class IdNameMixin(object):
        id = Column(Integer, primary_key=True)
        name = Column(String)
    
    class C1(declarative_base(), IdNameMixin):
        __tablename__ = 'C1'
    
    class C2(declarative_base(), IdNameMixin):
        __tablename__ = 'C2'
    
    print C1.__dict__['id'] is C2.__dict__['id']
    print C1.__dict__['name'] is C2.__dict__['name']
    

    EDIT: You might think this would result in C1 and C2 sharing the same Column objects, but as noted in the SQLAlchemy docs, Column objects are copied when originating from a mixin class. I've updated the code sample to demonstrate this behavior.

    0 讨论(0)
  • 2021-02-05 22:55

    Could you also use the Column's copy method? This way, fields can be defined independently of tables, and those fields that are reused are just field.copy()-ed.

    id = Column(Integer, primary_key = True)
    name = Column(String)
    
    class C1(declarative_base()):
        id = id.copy()
        name = name.copy()
        #...
    
    class C2(declarative_base()):
        id = id.copy()
        name = name.copy()
        #...
    
    0 讨论(0)
提交回复
热议问题