1 from datetime
import datetime
3 from sqlalchemy
import and_
, Column
, ForeignKey
, Index
4 from sqlalchemy
.orm
import relation
5 from sqlalchemy
.types
import DateTime
, Enum
, Integer
, Unicode
7 from spline
.model
.meta
import TableBase
8 from splinext
.users
import model
as users_model
13 class Forum(TableBase
):
14 __tablename__
= 'forums'
15 id = Column(Integer
, primary_key
=True, autoincrement
=True, nullable
=False)
16 name
= Column(Unicode(133), nullable
=False)
17 access_level
= Column(Enum(u
'normal', u
'soapbox', u
'archive', name
='forums_access_level'), nullable
=False, default
=u
'normal', server_default
=u
'normal')
19 def can_create_thread(self
, user
):
20 """Returns True ifff the named user can make a new thread in this
23 if not user
.can('forum:create-thread'):
26 if self
.access_level
== u
'soapbox' and \
27 not user
.can('forum:override-soapbox'):
30 if self
.access_level
== u
'archive' and \
31 not user
.can('forum:override-archive'):
36 class Thread(TableBase
):
37 __tablename__
= 'threads'
38 id = Column(Integer
, primary_key
=True, autoincrement
=True, nullable
=False)
39 forum_id
= Column(Integer
, ForeignKey('forums.id'), nullable
=False)
40 icon
= Column(Unicode(32), nullable
=True)
41 subject
= Column(Unicode(133), nullable
=False)
42 post_count
= Column(Integer
, nullable
=False, default
=0, index
=True)
44 def specific_post(self
, position
):
45 """Returns post number `position` in this thread.
47 Positions are one-indexed. Negative indexes are allowed.
50 # Handle negative indexes
52 position
= self
.post_count
+ position
+ 1
54 return self
.posts
.filter_by(position
=position
).one()
56 def can_create_post(self
, user
):
57 """Returns True ifff the named user can make a new post in this thread.
59 if not user
.can('forum:create-post'):
62 if self
.forum
.access_level
== u
'archive' and \
63 not user
.can('forum:override-archive'):
68 class Post(TableBase
):
69 __tablename__
= 'posts'
70 id = Column(Integer
, primary_key
=True, autoincrement
=True, nullable
=False)
71 thread_id
= Column(Integer
, ForeignKey('threads.id'), nullable
=False)
72 position
= Column(Integer
, nullable
=False)
73 author_user_id
= Column(Integer
, ForeignKey('users.id'), nullable
=False)
74 posted_time
= Column(DateTime
, nullable
=False, index
=True, default
=datetime
.now
)
75 content
= Column(Unicode(5120), nullable
=False)
77 Index('thread_position', Post
.thread_id
, Post
.position
, unique
=True)
80 # XXX sort by time, how?
81 Forum
.threads
= relation(Thread
, order_by
=Thread
.id.desc(), lazy
='dynamic', backref
='forum')
83 Thread
.posts
= relation(Post
, order_by
=Post
.position
.asc(), lazy
='dynamic', backref
='thread')
84 Thread
.first_post
= relation(Post
, primaryjoin
=and_(Post
.thread_id
== Thread
.id, Post
.position
== 1), uselist
=False)
85 Thread
.last_post
= relation(Post
, primaryjoin
=and_(Post
.thread_id
== Thread
.id, Post
.position
== Thread
.post_count
), uselist
=False)
87 Post
.author
= relation(users_model
.User
, backref
='posts')