Подтвердить что ты не робот

Должен ли я создавать объекты mapper или использовать декларативный синтаксис в SQLAlchemy?

Существует два (три, но я не считаю Elixir, поскольку он не "официальный") способ определения постоянного объекта с помощью 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, но я хотел бы услышать убедительные аргументы для обоих подходы.

4b9b3361

Ответ 1

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

Невозможно ответить в целом.

Однако рассмотрим это.

Django ORM является строго декларативным - и людям это нравится.

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

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

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

  • Эликсир - это альтернатива спасению вас от поиска SQL.

Основной вопрос: "Вы хотите увидеть и коснуться SQL?"

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Ответ 4

на текущий момент (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)