map.connect('/users', controller='users', action='list')
map.connect('user_page', '/users/{name}', controller='users', action='view')
+ # Comments
+ with map.submapper(controller='comments') as sub:
+ sub.connect('/*owner_url/comments', action='thread')
+ sub.connect('/*owner_url/comments/reply', action='reply')
+ sub.connect('/*owner_url/comments/reply_done', action='reply_done', **require_POST)
with map.submapper(controller="art") as sub:
sub.connect('new_art', '/art/new', action="new")
import elixir
from floof.model.art import Art, Rating
+from floof.model.comments import Discussion
from sqlalchemy.exceptions import IntegrityError
# TODO: login required
def create(self):
c.art = Art(uploader=c.user, **request.params)
+ c.art.discussion = Discussion(count=0)
try:
elixir.session.commit()
--- /dev/null
+import logging
+
+import elixir
+from pylons import config, request, response, session, tmpl_context as c
+from pylons.controllers.util import abort, redirect, redirect_to
+
+from floof.lib.base import BaseController, render
+from floof.model.art import Art
+from floof.model.comments import Comment
+
+log = logging.getLogger(__name__)
+
+def find_owner(owner_url):
+ """Returns whatever thing owns a group of comments."""
+
+ # Need to prepend a slash to make this an absolute URL
+ route = config['routes.map'].match('/' + owner_url)
+
+ if route['action'] not in ('show', 'view'):
+ abort(404)
+
+ if route['controller'] == 'art':
+ model = Art
+ else:
+ abort(404)
+
+ owner = model.query.get(route['id'])
+ if not owner:
+ abort(404)
+
+ return owner
+
+
+class CommentsController(BaseController):
+
+ def thread(self, owner_url):
+ """View a thread of comments, either attached to an item or starting
+ from a parent comment belonging to that item.
+ """
+ owner_object = find_owner(owner_url)
+ c.comments = owner_object.discussion.comments
+ return render('/comments/thread.mako')
+
+ def reply(self, owner_url):
+ """Reply to a comment or discussion."""
+ return render('/comments/reply.mako')
+
+ def reply_done(self, owner_url):
+ """Finish replying to a comment or discussion."""
+ # XXX form validation woo
+
+ new_comment = Comment(
+ text=request.params['text'],
+ user=c.user,
+ )
+
+ owner_object = find_owner(owner_url)
+ discussion = owner_object.discussion
+ discussion.comments.append(new_comment)
+ elixir.session.commit()
+
+ return redirect('/' + owner_url, code=301)
"""
from pylons.controllers import WSGIController
from pylons.templating import render_mako as render
-from pylons import config
-from floof import model
+from pylons import config, session, tmpl_context as c
+from routes import request_config
-from pylons import session, tmpl_context as c
+from floof import model
from floof.model.users import User
class BaseController(WSGIController):
# NOTE: This could have been implemented as a middleware =]
def __before__(self):
+ c.route = request_config().mapper_dict
+
# Fetch current user object
try:
c.user = User.query.get(session['user_id'])
abort(404)
return obj
+def get_comment_owner_url(**route):
+ """Given a view route, returns the owner_url route parameter for generating
+ comment URLs.
+ """
+ # url() returns URLs beginning with a slash. We just need to strip it.
+ return url(**route)[1:]
+import datetime
+
from elixir import *
class Discussion(Entity):
comments = OneToMany('Comment')
class Comment(Entity):
- discussion = ManyToOne('Discussion')
+ time = Field(DateTime, default=datetime.datetime.now)
text = Field(Unicode(65536))
+ discussion = ManyToOne('Discussion')
+ user = ManyToOne('User')
<%inherit file="/base.mako" />
-<%namespace name="comments" file="/comments.mako" />
+<%namespace name="comments" file="/comments/lib.mako" />
<%! from floof.model.art import Rating %>
<img class="full" src="${c.art.get_path()}">
-${comments.entire_thread(c.art.discussion)}
+${comments.comment_block(c.art.discussion.comments)}
+++ /dev/null
-<%def name="entire_thread(discussion)">
-<%
- if not discussion:
- return
-%>\
-<ul>
- % for comment in discussion.comments:
- <li>${comment.text}</li>
- % endfor
-</ul>
-</%def>
--- /dev/null
+<%def name="comment_block(comments)">
+<p><a href="${url(controller='comments', action='thread', owner_url=h.get_comment_owner_url(**c.route))}">View all</a></p>
+<p><a href="${url(controller='comments', action='reply', owner_url=h.get_comment_owner_url(**c.route))}">Reply</a></p>
+${comment_thread(comments)}
+</%def>
+
+<%def name="comment_thread(comments)">
+% for comment in comments:
+<div class="comment">
+ <div class="user">${comment.user.name}</div>
+ <div class="time">${comment.time}</div>
+ <p>${comment.text}</p>
+</div>
+% endfor
+</%def>
--- /dev/null
+<%inherit file="/base.mako" />
+<%namespace name="comments" file="/comments/lib.mako" />
+
+<h1>Reply</h1>
+${h.form(url(controller='comments', action='reply_done', owner_url=c.owner_url), method='post')}
+<dl class="form">
+ <dt>Comment</dt>
+ <dd>${h.textarea('text')}</dd>
+
+ <dd>${h.submit(None, 'Post')}</dd>
+</dl>
+${h.end_form()}
--- /dev/null
+<%inherit file="/base.mako" />
+<%namespace name="comments" file="/comments/lib.mako" />
+
+<h1>Comments</h1>
+${comments.comment_thread(c.comments)}
--- /dev/null
+from floof.tests import *
+
+class TestCommentsController(TestController):
+
+ def test_index(self):
+ response = self.app.get(url(controller='comments', action='index'))
+ # Test response...