Flesh out core forum schema.
[zzz-spline-forum.git] / splinext / forum / model / __init__.py
1 from sqlalchemy import and_, Column, ForeignKey, Index
2 from sqlalchemy.orm import relation
3 from sqlalchemy.types import DateTime, Integer, Unicode
4
5 from spline.model.meta import TableBase
6 from splinext.users import model as users_model
7
8
9 ### Core
10
11 class Forum(TableBase):
12 __tablename__ = 'forums'
13 id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
14 name = Column(Unicode(133), nullable=False)
15
16 class Thread(TableBase):
17 __tablename__ = 'threads'
18 id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
19 forum_id = Column(Integer, ForeignKey('forums.id'), nullable=False)
20 icon = Column(Unicode(32), nullable=True)
21 subject = Column(Unicode(133), nullable=False)
22 post_count = Column(Integer, nullable=False, default=0, index=True)
23
24 def specific_post(self, position):
25 """Returns post number `position` in this thread.
26
27 Positions are one-indexed. Negative indexes are allowed.
28 """
29
30 # Handle negative indexes
31 if position < 0:
32 position = self.post_count + position + 1
33
34 return self.posts.filter_by(position=position).one()
35
36 class Post(TableBase):
37 __tablename__ = 'posts'
38 id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
39 thread_id = Column(Integer, ForeignKey('threads.id'), nullable=False)
40 position = Column(Integer, nullable=False)
41 author_user_id = Column(Integer, ForeignKey('users.id'), nullable=False)
42 posted_time = Column(DateTime, nullable=False, index=True)
43 content = Column(Unicode(5120), nullable=False)
44
45 Index('thread_position', Post.thread_id, Post.position, unique=True)
46
47
48 # XXX sort by time, how?
49 Forum.threads = relation(Thread, order_by=Thread.id.desc(), lazy='dynamic', backref='forum')
50
51 Thread.posts = relation(Post, order_by=Post.posted_time.desc(), lazy='dynamic', backref='thread')
52 Thread.first_post = relation(Post, primaryjoin=and_(Post.thread_id == Thread.id, Post.position == 1), uselist=False)
53 Thread.last_post = relation(Post, primaryjoin=and_(Post.thread_id == Thread.id, Post.position == Thread.post_count), uselist=False)
54
55 Post.author = relation(users_model.User, backref='posts')