📄 mappers.py
字号:
"""mapper.py - defines mappers for domain objects, mapping operations"""import zblog.tables as tablesimport zblog.user as userfrom zblog.blog import *from sqlalchemy import *from sqlalchemy.orm import *import sqlalchemy.util as utildef zblog_mappers(): # User mapper. Here, we redefine the names of some of the columns to # different property names. normally the table columns are all sucked in # automatically. mapper(user.User, tables.users, properties={ 'id':tables.users.c.user_id, 'name':tables.users.c.user_name, 'group':tables.users.c.groupname, 'crypt_password':tables.users.c.password, }) # blog mapper. this contains a reference to the user mapper, and also # installs a "backreference" on that relationship to handle it in both # ways. this will also attach a 'blogs' property to the user mapper. mapper(Blog, tables.blogs, properties={ 'id':tables.blogs.c.blog_id, 'owner':relation(user.User, lazy=False, backref=backref('blogs', cascade="all, delete-orphan")), }) # topic mapper. map all topic columns to the Topic class. mapper(Topic, tables.topics) # TopicAssocation mapper. This is an "association" object, which is # similar to a many-to-many relationship except extra data is associated # with each pair of related data. because the topic_xref table doesnt # have a primary key, the "primary key" columns of a TopicAssociation are # defined manually here. mapper(TopicAssociation,tables.topic_xref, primary_key=[tables.topic_xref.c.post_id, tables.topic_xref.c.topic_id], properties={ 'topic':relation(Topic, lazy=False), }) # Post mapper, these are posts within a blog. # since we want the count of comments for each post, create a select that # will get the posts and count the comments in one query. posts_with_ccount = select( [c for c in tables.posts.c if c.key != 'body'] + [ func.count(tables.comments.c.comment_id).label('comment_count') ], from_obj = [ outerjoin(tables.posts, tables.comments) ], group_by=[ c for c in tables.posts.c if c.key != 'body' ] ) .alias('postswcount') # then create a Post mapper on that query. # we have the body as "deferred" so that it loads only when needed, the # user as a Lazy load, since the lazy load will run only once per user and # its usually only one user's posts is needed per page, the owning blog is # a lazy load since its also probably loaded into the identity map # already, and topics is an eager load since that query has to be done per # post in any case. mapper(Post, posts_with_ccount, properties={ 'id':posts_with_ccount.c.post_id, 'body':deferred(tables.posts.c.body), 'user':relation(user.User, lazy=True, backref=backref('posts', cascade="all, delete-orphan")), 'blog':relation(Blog, lazy=True, backref=backref('posts', cascade="all, delete-orphan")), 'topics':relation(TopicAssociation, lazy=False, cascade="all, delete-orphan", backref='post') }, order_by=[desc(posts_with_ccount.c.datetime)]) # comment mapper. This mapper is handling a hierarchical relationship on # itself, and contains a lazy reference both to its parent comment and its # list of child comments. mapper(Comment, tables.comments, properties={ 'id':tables.comments.c.comment_id, 'post':relation(Post, lazy=True, backref=backref('comments', cascade="all, delete-orphan")), 'user':relation(user.User, lazy=False, backref=backref('comments', cascade="all, delete-orphan")), 'parent':relation(Comment, primaryjoin=(tables.comments.c.parent_comment_id == tables.comments.c.comment_id), foreign_keys=[tables.comments.c.comment_id], lazy=True, uselist=False), 'replies':relation(Comment, primaryjoin=(tables.comments.c.parent_comment_id == tables.comments.c.comment_id), lazy=True, uselist=True, cascade="all"), })# we define one special find-by for the comments of a post, which is going to# make its own "noload" mapper and organize the comments into their correct# hierarchy in one pass. hierarchical data normally needs to be loaded by# separate queries for each set of children, unless you use a proprietary# extension like CONNECT BY.def find_by_post(post): """returns a hierarchical collection of comments based on a given criterion. Uses a mapper that does not lazy load replies or parents, and instead organizes comments into a hierarchical tree when the result is produced. """ q = session().query(Comment).options(noload('replies'), noload('parent')) comments = q.select_by(post_id=post.id) result = [] d = {} for c in comments: d[c.id] = c if c.parent_comment_id is None: result.append(c) c.parent=None else: parent = d[c.parent_comment_id] parent.replies.append(c) c.parent = parent return resultComment.find_by_post = staticmethod(find_by_post)def start_session(): """creates a new session for the start of a request.""" trans.session = create_session(bind_to=zblog.database.engine )def session(): return trans.session
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -