Как сделать составные столбцы с SQLAlchemy декларативным? - PullRequest
4 голосов
/ 05 марта 2012

Я часто делаю модели с Text столбцами, которые содержат форматированный Markdown форматированный текст.Мои модели выглядят так:

class Document(Base):
    id = Column(Integer, primary_key=True)
    title = Column(Unicode(250))
    description = Column(Text)
    description_html = Column(Text)    

Мои формы редактирования (а) считывают и записывают в description, а затем (б) записывают версию в формате Markdown в description_html.Мои (Jinja2) шаблоны представления (c) загружают версию HTML с {{ doc.description_html|safe }}.

. Я хотел бы сократить эти три повторяющиеся операции в одно определение столбца, например:

class Document(Base):
    id = Column(Integer, primary_key=True)
    title = Column(Unicode(250))
    description = Column(MarkdownText)

Где MarkdownText - это новый тип столбца, который:

  1. Делает два столбца в таблице базы данных (description и description_html),
  2. При записи в столбец также записываетОтформатируйте версию в столбце html и
  3. Предоставляет метод __html__(), который возвращает содержимое столбца html.Это позволит использовать его из шаблона Jinja2 как {{ doc.description }} без фильтра safe.

Вопрос: Возможен ли № 1?Могу ли я определить столбец, который состоит из двух столбцов?

Ответы [ 2 ]

3 голосов
/ 05 марта 2012

Вот и все - теперь с составными столбцами:

from sqlalchemy import create_engine
from sqlalchemy import Column, Integer, Text
from sqlalchemy.orm import composite, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///')
session = sessionmaker(bind=engine)()
Base = declarative_base()

class MarkdownText(object):

    def __init__(self, text):
        self._text = text
        self._html = "<html>%s</html>" % text

    @classmethod
    def _from_db(cls, text, html):
        mt = MarkdownText(text)
        mt._html = html
        return mt

    def __composite_values__(self):
        return (self._text, self._html)

    def __str__(self):
        return self._text

    @property
    def __html__(self):
        return self._html

class Foo(Base):
    __tablename__ = 'foo'

    id = Column(Integer, primary_key=True)
    a = composite(MarkdownText._from_db,
                     Column('_text', Text),
                     Column('_html', Text))

    def __init__(self, a):
        self.a = MarkdownText(a)

    def __repr__(self):
        return '(%s)' % (self.a)

Base.metadata.create_all(engine)

session.add_all([Foo('test'), Foo('nips')])
session.commit()
x = session.query(Foo).all()
print x
print x[0].a.__html__
print x[0].a

И это дает нам приятное:

[(test), (nips)]
<html>test</html>
test
2 голосов
/ 05 марта 2012

Вместо того, чтобы отвечать на ваши вопросы, лучше спросить вас: «Вы действительно хотите хранить как простой текст, так и текст HTML в базе данных?». Вот как бы я это сделал:

def text2html(text):
    # TODO: Implement me!
    pass

class Document(Base):
    id = Column(Integer, primary_key=True)
    title = Column(Unicode(250))
    description = Column(Text)

    @property
    def description_html(self):
        return text2html(self.description)

И с учетом html-описания можно получить доступ так же, как document.description_html ...

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