How to create compound columns with SQLAlchemy declaration?

I often make models with Text columns that contain Markdown formatted richtext. My models look like this:

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

My right forms (a) read and write to description , and then (b) write a formatted version of Markdown in description_html . My templates (Jinja2) (c) download the HTML version using {{ doc.description_html|safe }} .

I would like to shorten these three repetitive operations into one column definition, for example:

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

Where MarkdownText is a new column type that:

  • Makes two columns in a database table (description and description_html),
  • After writing to the column, it also writes a formatted version of Markdown to the html column and
  • Provides the __html__() method, which returns the contents of an html column. This will allow you to use the Jinja2 template as {{ doc.description }} without the safe filter.

Question: Is it possible 1? Is it possible to define a column that creates two columns?

+4
source share
2 answers

Here we go - now with composite columns:

 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 

And it gives us a pleasant:

 [(test), (nips)] <html>test</html> test 
+3
source

Instead of answering your scores, I’d better ask you: "Do you really want to store both plain text and html text in a database?" Here's how I do it:

 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) 

And bearing in mind that the html description can be obtained in the same way as document.description_html ...

+2
source

Source: https://habr.com/ru/post/1399757/


All Articles