Persistence¶
For those programmers who have an object oriented model (which is recommended, but not strictly necessary to use Reahl), we provide glue to the object relational mapping tools provided by SqlAlchemy.
Reahl allows you to build and distribute parts of your program as reusable components that do not contain knowledge about the web application such components will be used in. Reahl extends existing database migration tools to make it possible to write database migrations per component regardless of where that component will be used. (See the tutorial for more on this topic.)
Here is an example showing the use of SqlAlchemy. Reahl merely provides versions of SqlAlchemy’s Session, Base and metadata objects for use with Reahl applications. Further use is just normal SqlAlchemy.
Our example first comes up with only a (somewhat prettied up) form asking the user to leave a comment:
When the user clicks on submit, the new comment is persisted in the database. When the page is refreshed, the form is still rendered, but a list of all the comments in the database is shown below it:
In the example’s source code (below), the Comment class is persisted via SqlAlchemy’s declarative:
from __future__ import print_function, unicode_literals, absolute_import, division
from sqlalchemy import Column, UnicodeText, Integer
from reahl.sqlalchemysupport import Session, Base
from reahl.web.fw import UserInterface
from reahl.web.ui import Button, Form, FieldSet, LabelledBlockInput
from reahl.web.ui import HTML5Page, P, Div, TextInput
from reahl.component.modelinterface import exposed, EmailField, Field
from reahl.component.modelinterface import Event, Action
class PersistenceUI(UserInterface):
def assemble(self):
self.define_view('/', title='Persistence demo', page=HomePage.factory())
class HomePage(HTML5Page):
def __init__(self, view):
super(HomePage, self).__init__(view, style='basic')
self.body.add_child(CommentForm(view))
for comment in Session.query(Comment).all():
self.body.add_child(CommentBox(view, comment))
class Comment(Base):
__tablename__ = 'features_comment'
id = Column(Integer, primary_key=True)
email_address = Column(UnicodeText)
text = Column(UnicodeText)
@exposed
def fields(self, fields):
fields.email_address = EmailField(label='Email address', required=True)
fields.text = Field(label='Comment', required=True)
@exposed
def events(self, events):
events.submit = Event(label='Submit', action=Action(self.submit))
def submit(self):
Session.add(self)
class CommentForm(Form):
def __init__(self, view):
super(CommentForm, self).__init__(view, 'myform')
new_comment = Comment()
grouped_inputs = FieldSet(view, legend_text='Leave a comment')
self.add_child(grouped_inputs)
email_input = TextInput(self, new_comment.fields.email_address)
grouped_inputs.add_child( LabelledBlockInput(email_input) )
text_input = TextInput(self, new_comment.fields.text)
grouped_inputs.add_child( LabelledBlockInput(text_input) )
self.define_event_handler(new_comment.events.submit)
grouped_inputs.add_child( Button(self, new_comment.events.submit) )
class CommentBox(Div):
def __init__(self, view, comment):
super(CommentBox, self).__init__(view)
comment_text = 'By %s: %s' % (comment.email_address, comment.text)
self.add_child(P(view, text=comment_text))