Должен ли я создавать объекты Mapper или использовать декларативный синтаксис в SQLAlchemy? - PullRequest
41 голосов
/ 21 сентября 2009

Существует два (три, но я не считаю эликсира , поскольку это не "официальный") способа определения постоянного объекта с помощью SQLAlchemy :

Явный синтаксис для объектов отображения

from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.orm import mapper

metadata = MetaData()

users_table = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
)

class User(object):
    def __init__(self, name):
        self.name = name

    def __repr__(self):
       return "<User('%s')>" % (self.name)

mapper(User, users_table) # &lt;Mapper at 0x...; User&gt;

Декларативный синтаксис

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class User(Base):
     __tablename__ = 'users'
     id = Column(Integer, primary_key=True)
     name = Column(String)

     def __init__(self, name):
         self.name = name

     def __repr__(self):
         return "<User('%s')>" % (self.name)

Я вижу, что при использовании объектов mapper я полностью отделяю определение ORM от бизнес-логики, а при использовании декларативного синтаксиса всякий раз, когда я изменяю класс бизнес-логики, я могу редактировать класс базы данных (который в идеале должен немного редактировать).

В чем я не совсем уверен, какой подход более удобен для бизнес-приложений?

Мне не удалось найти сравнение между двумя методами картирования, чтобы решить, какой из них лучше подходит для моего проекта.

Я склоняюсь к использованию «обычного» способа (то есть не декларативного расширения), так как это позволяет мне «скрывать» и не допускать бизнес-представления ко всей логике ORM, но я хотел бы услышать убедительные аргументы для обоих подходов.

Ответы [ 4 ]

24 голосов
/ 21 сентября 2009

«В чем я не совсем уверен, какой подход более удобен для бизнес-приложений?»

Нельзя ответить вообще.

Однако учтите это.

ORM Django строго декларативен - и тому подобное.

SQLAlchemy делает несколько вещей, не все из которых имеют отношение ко всем проблемам.

  1. SQLAlchemy создает специфичный для БД SQL из Python общего назначения. Если вы хотите связываться с SQL или сопоставить классы Python с существующими таблицами, вам придется использовать явные отображения, потому что вы сосредоточены на SQL, а не на бизнес-объектах и ​​ORM.

  2. SQLAlchemy может использовать декларативный стиль (например, Django), чтобы создать все для вас. Если вы хотите этого, то вы отказываетесь от явного написания определений таблиц и явно возитесь с SQL.

  3. Elixir - это альтернатива избавлению от необходимости смотреть на SQL.

Фундаментальный вопрос: «Хочешь увидеть и потрогать SQL?»

Если вы думаете, что прикосновение к SQL делает вещи более «обслуживаемыми», вам придется использовать явные сопоставления.

Если вы думаете, что сокрытие SQL делает вещи более «обслуживаемыми», тогда вы должны использовать декларативный стиль.

  • Если вы думаете, что Elixir может отклониться от SQLAlchemy или каким-то образом не выполнить его обещание, не используйте его.

  • Если вы думаете, что Elixir вам поможет, используйте его.

15 голосов
/ 21 сентября 2009

В нашей команде мы остановились на декларативном синтаксисе.

Обоснование:

  • metadata тривиально, если нужно: User.metadata.
  • Ваш класс User, благодаря подклассу Base, имеет хороший ctor, который принимает kwargs для всех полей. Полезно для тестирования и прочего. Например: user=User(name='doe', password='42'). Так что не нужно писать ctor!
  • Если вы добавляете атрибут / столбец, вам нужно сделать это только один раз. «Не повторяйся» - хороший принцип.

Относительно "не допустить ORM в бизнес-представление": в действительности ваш класс User, определенный "обычным" способом, получает серьезную махинацию с SA, когда функция mapper справляется с этим. ИМХО, декларативный способ более честен, потому что он кричит: «этот класс используется в сценариях ORM и не может обрабатываться так же, как если бы вы обращались с простыми объектами, отличными от ORM».

5 голосов
/ 21 сентября 2009

Я обнаружил, что использование объектов mapper намного проще, чем декларативный синтаксис, если вы используете sqlalchemy-migrate для создания версии схемы базы данных (и это необходимо для бизнес-приложения с моей точки зрения Посмотреть). Если вы используете объекты mapper, вы можете просто скопировать / вставить объявления таблиц в версии миграции и использовать простой API для изменения таблиц в базе данных. Декларативный синтаксис усложняет эту задачу, поскольку вам необходимо отфильтровать все вспомогательные функции из определений классов после их копирования в версию миграции.

Кроме того, мне кажется, что сложные отношения между таблицами более четко выражены с помощью синтаксиса объектов картографирования, но это может быть субъективным.

1 голос
/ 10 мая 2019

по состоянию на текущий (2019 г.), много лет спустя sqlalchemy v1.3 допускает гибридный подход с лучшим из обоих миров

https://docs.sqlalchemy.org/en/13/orm/extensions/declarative/table_config.html#using-a-hybrid-approach-with-table

metadata = MetaData()

users_table = Table('users', metadata,
  Column('id', Integer, primary_key=True),
  Column('name', String),
)

# possibly in a different file/place the orm-declaration
Base = declarative_base(metadata)

class User(Base):
  __table__ = Base.metadata.tables['users']
  def __str__(): 
    return "<User('%s')>" % (self.name)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...