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 description
= Column(Unicode(1024), nullable
=False, default
=u
'', server_default
=u
'')
18 access_level
= Column(Enum(u
'normal', u
'soapbox', u
'archive', name
='forums_access_level'), nullable
=False, default
=u
'normal', server_default
=u
'normal')
20 def can_create_thread(self
, user
):
21 """Returns True ifff the named user can make a new thread in this
24 if not user
.can('forum:create-thread'):
27 if self
.access_level
== u
'soapbox' and \
28 not user
.can('forum:override-soapbox'):
31 if self
.access_level
== u
'archive' and \
32 not user
.can('forum:override-archive'):
37 class Thread(TableBase
):
38 __tablename__
= 'threads'
39 id = Column(Integer
, primary_key
=True, autoincrement
=True, nullable
=False)
40 forum_id
= Column(Integer
, ForeignKey('forums.id'), nullable
=False)
41 icon
= Column(Unicode(32), nullable
=True)
42 subject
= Column(Unicode(133), nullable
=False)
43 post_count
= Column(Integer
, nullable
=False, default
=0, index
=True)
45 def specific_post(self
, position
):
46 """Returns post number `position` in this thread.
48 Positions are one-indexed. Negative indexes are allowed.
51 # Handle negative indexes
53 position
= self
.post_count
+ position
+ 1
55 return self
.posts
.filter_by(position
=position
).one()
57 def can_create_post(self
, user
):
58 """Returns True ifff the named user can make a new post in this thread.
60 if not user
.can('forum:create-post'):
63 if self
.forum
.access_level
== u
'archive' and \
64 not user
.can('forum:override-archive'):
69 class Post(TableBase
):
70 __tablename__
= 'posts'
71 id = Column(Integer
, primary_key
=True, autoincrement
=True, nullable
=False)
72 thread_id
= Column(Integer
, ForeignKey('threads.id'), nullable
=False)
73 position
= Column(Integer
, nullable
=False)
74 author_user_id
= Column(Integer
, ForeignKey('users.id'), nullable
=False)
75 posted_time
= Column(DateTime
, nullable
=False, index
=True, default
=datetime
.now
)
76 raw_content
= Column(Unicode(5120), nullable
=False)
77 content
= Column(Unicode(5120), nullable
=False)
79 Index('thread_position', Post
.thread_id
, Post
.position
, unique
=True)
82 # XXX sort by time, how?
83 Forum
.threads
= relation(Thread
, lazy
='dynamic', backref
='forum')
85 Thread
.posts
= relation(Post
, order_by
=Post
.position
.asc(), lazy
='dynamic', backref
='thread')
86 Thread
.first_post
= relation(Post
, primaryjoin
=and_(Post
.thread_id
== Thread
.id, Post
.position
== 1), foreign_keys
=[Post
.thread_id
], innerjoin
=True, uselist
=False, viewonly
=True)
87 # XXX THIS WILL NEED TO CHANGE when posts can be deleted! Or change what 'position' means
88 Thread
.last_post
= relation(Post
, primaryjoin
=and_(Post
.thread_id
== Thread
.id, Post
.position
== Thread
.post_count
), foreign_keys
=[Post
.thread_id
], innerjoin
=True, uselist
=False, viewonly
=True)
90 Post
.author
= relation(users_model
.User
, backref
='posts', innerjoin
=True)