SQLAlchemy: избегание повторения в определении класса декларативного стиля - PullRequest
11 голосов
/ 02 сентября 2010

Я использую SQLAlchemy, и многие классы в моей объектной модели имеют одинаковые два атрибута: id и (целое число и первичный ключ) и name (строка)Я стараюсь не объявлять их в каждом классе следующим образом:

class C1(declarative_base()):
    id = Column(Integer, primary_key = True)
    name = Column(String)
    #...

class C2(declarative_base()):
    id = Column(Integer, primary_key = True)
    name = Column(String)
    #...

Какой хороший способ сделать это?Я пытался использовать метаклассы, но это еще не сработало.

Ответы [ 3 ]

10 голосов
/ 02 сентября 2010

Вы можете выделить ваши общие атрибуты в класс mixin и умножить его наследовать вместе с 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']

РЕДАКТИРОВАТЬ : Вы можете подумать, что это приведет к тому, что C1 и C2 будут использовать одни и те же Column объекты, но, как отмечено в документах SQLAlchemy , объекты Column скопировано при создании из класса mixin. Я обновил пример кода, чтобы продемонстрировать это поведение.

2 голосов
/ 25 мая 2011

Не могли бы вы также использовать метод копирования столбца?Таким образом, поля могут быть определены независимо от таблиц, а те поля, которые используются повторно, просто field.copy () - ред.

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()
    #...
1 голос
/ 03 сентября 2010

Я думаю, я заставил его работать.

Я создал метакласс, который наследуется от DeclarativeMeta, и сделал его метаклассом C1 и C2.В этом новом метаклассе я просто сказал:

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)

И, похоже, он работает нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...