Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: laoqiu/pypress
base: master
...
head fork: silverymoon/pypress
compare: master
Checking mergeability… Don’t worry, you can still create the pull request.
  • 2 commits
  • 42 files changed
  • 0 commit comments
  • 1 contributor
Commits on Sep 29, 2011
@silverymoon silverymoon * removed scary chinese wysiwyg editor
* added uploads to database, views and model
* renamed upload directory, can upload nearly everything
* added simple pages without comments
*
45d63e7
@silverymoon silverymoon * removed chinese wysiwyg editor
* added upload management with model, view and db
* added simple pages without comments
* sorting entries by date
* added recaptcha field to comments
* blog entries can be in creole markup
* removed twitter stuff
* removed routes for signup links
* removed routes for user submitted links
* added fieldsets to nearly all forms
* fixed some typos in error pages
* months without entries don't crop up in archive
* removed people pages
* numerous smaller changes (sorry, didn't use git while developing, my bad!)
856a01f
Showing with 634 additions and 686 deletions.
  1. +7 −1 README
  2. +49 −35 pypress/__init__.py
  3. +14 −10 pypress/config.cfg
  4. +2 −2 pypress/extensions.py
  5. +1 −1  pypress/forms/__init__.py
  6. +24 −15 pypress/forms/blog.py
  7. +26 −10 pypress/helpers.py
  8. +1 −1  pypress/models/__init__.py
  9. +105 −71 pypress/models/blog.py
  10. BIN  pypress/static/favicon.ico
  11. +35 −28 pypress/static/js/public.js
  12. +21 −22 pypress/templates/account/login.html
  13. +2 −3 pypress/templates/account/signup.html
  14. +3 −4 pypress/templates/blog/_archive.html
  15. +1 −0  pypress/templates/blog/_comment.html
  16. +2 −1  pypress/templates/blog/_postnow.html
  17. +4 −4 pypress/templates/blog/_search.html
  18. +1 −1  pypress/templates/blog/_tags.html
  19. +15 −25 pypress/templates/blog/add_comment.html
  20. +26 −28 pypress/templates/blog/add_link.html
  21. +22 −0 pypress/templates/blog/add_upload.html
  22. +1 −11 pypress/templates/blog/archive.html
  23. +6 −12 pypress/templates/blog/list.html
  24. +22 −0 pypress/templates/blog/page.html
  25. +1 −11 pypress/templates/blog/people.html
  26. +3 −3 pypress/templates/blog/search_result.html
  27. +27 −111 pypress/templates/blog/submit.html
  28. +1 −11 pypress/templates/blog/tags.html
  29. +31 −0 pypress/templates/blog/uploads.html
  30. +20 −27 pypress/templates/blog/view.html
  31. +0 −1  pypress/templates/errors/403.html
  32. +3 −1 pypress/templates/errors/404.html
  33. +3 −3 pypress/templates/macros/_forms.html
  34. +7 −8 pypress/templates/macros/_post.html
  35. +1 −1  pypress/views/__init__.py
  36. +10 −75 pypress/views/account.py
  37. +4 −4 pypress/views/comment.py
  38. +6 −6 pypress/views/feeds.py
  39. +30 −115 pypress/views/frontend.py
  40. +7 −7 pypress/views/link.py
  41. +19 −17 pypress/views/post.py
  42. +71 −0 pypress/views/uploads.py
View
8 README
@@ -1,4 +1,4 @@
-This is a team blog by flask.
+This is a team blog by flask.
Thanks for flask_website and newsmeme at http://flask.pocoo.org/community/poweredby/
1. install
@@ -12,8 +12,14 @@ Flask-Mail
Flask-Script
Flask-Babel
Flask-Themes
+Flask-Uploads
+Flask-Creole
+creole
+oauth2
markdown
blinker
+pygments
+recaptcha-client
install example:
easy_install flask
View
84 pypress/__init__.py
@@ -10,6 +10,7 @@
import os
import logging
import datetime
+import re
from logging.handlers import SMTPHandler, RotatingFileHandler
from werkzeug import parse_date
@@ -20,53 +21,65 @@
from flaskext.themes import setup_themes
from flaskext.principal import Principal, RoleNeed, UserNeed, identity_loaded
from flaskext.uploads import configure_uploads
+from flaskext.creole import Creole
from pypress import views, helpers
from pypress.models import User, Post, Tag, Link, Comment
-from pypress.extensions import db, mail, cache, photos
-from pypress.helpers import render_template
+from pypress.extensions import db, mail, cache, uploader
+from pypress.helpers import render_template, creole_make_img
DEFAULT_APP_NAME = 'pypress'
-DEFAULT_MODULES = (
+DEFAULT_BLUEPRINTS = (
(views.frontend, ""),
(views.post, "/post"),
(views.comment, "/comment"),
(views.account, "/account"),
- (views.link, "/link"),
(views.feeds, "/feeds"),
+ (views.uploads, '/uploads'),
)
-def create_app(config=None, modules=None):
+def create_app(config=None, blueprints=None):
+
+ if blueprints is None:
+ blueprints = DEFAULT_BLUEPRINTS
- if modules is None:
- modules = DEFAULT_MODULES
-
app = Flask(DEFAULT_APP_NAME)
-
+
# config
app.config.from_pyfile(config)
-
+
configure_extensions(app)
-
+
configure_identity(app)
configure_logging(app)
configure_errorhandlers(app)
configure_before_handlers(app)
configure_template_filters(app)
configure_context_processors(app)
- configure_uploads(app, (photos,))
+ configure_uploads(app, (uploader,))
configure_i18n(app)
-
+ configure_creole(app)
+
# register module
- configure_modules(app, modules)
+ configure_blueprints(app, blueprints)
return app
+def configure_creole(app):
+ creole = Creole(app, custom_markup=[(re.compile("%%(?P<src>[^%?|]+)(\?(?P<width>\d+)x(?P<height>\d+))?(\|(?P<alt>[^%]+))?%%"), helpers.creole_make_img)])
+
+ @creole.macro('pth')
+ def media_path(name, environ, body, is_block):
+ return "/static/uploads/"
+
+ @app.template_filter()
+ def creolify(text):
+ return unicode(creole.creole2html(text), 'utf-8')
def configure_extensions(app):
- # configure extensions
+ # configure extensions
db.init_app(app)
mail.init_app(app)
cache.init_app(app)
@@ -88,7 +101,7 @@ def configure_i18n(app):
@babel.localeselector
def get_locale():
- accept_languages = app.config.get('ACCEPT_LANGUAGES',['en','zh'])
+ accept_languages = app.config.get('ACCEPT_LANGUAGES',['en','de'])
return request.accept_languages.best_match(accept_languages)
@@ -100,7 +113,7 @@ def tags():
if tags is None:
tags = Tag.query.cloud()
cache.set("tags", tags)
- return dict(tags=tags)
+ return dict(tags=tags)
@app.context_processor
def links():
@@ -108,14 +121,14 @@ def links():
if links is None:
links = Link.query.filter(Link.passed==True).limit(10).all()
cache.set("links", links)
- return dict(links=links)
+ return dict(links=links)
@app.context_processor
def archives():
archives = cache.get("archives")
if archives is None:
- begin_post = Post.query.order_by('created_date').first()
-
+ begin_post = Post.query.filter(Post._page == False).order_by('created_date').first()
+
now = datetime.datetime.now()
begin = begin_post.created_date if begin_post else now
@@ -126,14 +139,15 @@ def archives():
date = begin
for i in range(total):
- if date.month<12:
+ if date.month<12:
date = datetime.datetime(date.year,date.month+1,1)
else:
date = datetime.datetime(date.year+1, 1, 1)
- archives.append(date)
+ if Post.query.archive(date.year, date.month, None).count() > 0:
+ archives.append(date)
archives.reverse()
cache.set("archives", archives)
-
+
return dict(archives=archives)
@app.context_processor
@@ -143,7 +157,7 @@ def latest_comments():
latest_comments = Comment.query.order_by(Comment.created_date.desc()) \
.limit(5).all()
cache.set("latest_comments", latest_comments)
- return dict(latest_comments=latest_comments)
+ return dict(latest_comments=latest_comments)
@app.context_processor
def config():
@@ -151,7 +165,7 @@ def config():
def configure_template_filters(app):
-
+
@app.template_filter()
def timesince(value):
return helpers.timesince(value)
@@ -175,7 +189,7 @@ def format_datetime(time,s='full'):
@app.template_filter()
def twitter_date(date):
return parse_date(date)
-
+
@app.template_filter()
def code_highlight(html):
return helpers.code_highlight(html)
@@ -193,14 +207,14 @@ def authenticate():
def configure_errorhandlers(app):
-
+
@app.errorhandler(401)
def unauthorized(error):
if request.is_xhr:
return jsonfiy(error=_("Login required"))
flash(_("Please login to see this page"), "error")
return redirect(url_for("account.login", next=request.path))
-
+
@app.errorhandler(403)
def forbidden(error):
if request.is_xhr:
@@ -220,10 +234,10 @@ def server_error(error):
return render_template("errors/500.html", error=error)
-def configure_modules(app, modules):
-
- for module, url_prefix in modules:
- app.register_module(module, url_prefix=url_prefix)
+def configure_blueprints(app, blueprints):
+
+ for module, url_prefix in blueprints:
+ app.register_blueprint(module, url_prefix=url_prefix)
def configure_logging(app):
@@ -231,7 +245,7 @@ def configure_logging(app):
mail_handler = \
SMTPHandler(app.config['MAIL_SERVER'],
app.config['DEFAULT_MAIL_SENDER'],
- app.config['ADMINS'],
+ app.config['ADMINS'],
'application error',
(
app.config['MAIL_USERNAME'],
@@ -245,7 +259,7 @@ def configure_logging(app):
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]')
- debug_log = os.path.join(app.root_path,
+ debug_log = os.path.join(app.root_path,
app.config['DEBUG_LOG'])
debug_file_handler = \
@@ -257,7 +271,7 @@ def configure_logging(app):
debug_file_handler.setFormatter(formatter)
app.logger.addHandler(debug_file_handler)
- error_log = os.path.join(app.root_path,
+ error_log = os.path.join(app.root_path,
app.config['ERROR_LOG'])
error_file_handler = \
View
24 pypress/config.cfg
@@ -1,10 +1,10 @@
DEBUG = True
-SECRET_KEY = 'secret test'
+SECRET_KEY = 'My secret key'
-SQLALCHEMY_DATABASE_URI = 'sqlite:///test.db'
+SQLALCHEMY_DATABASE_URI = 'sqlite:///your.db'
SQLALCHEMY_ECHO = False
-UPLOADS_DEFAULT_DEST = '/path/to/pypress/static/'
+UPLOADS_DEFAULT_DEST = '/path/to/wherever'
UPLOADS_DEFAULT_URL = '/static'
CACHE_TYPE = "simple"
@@ -14,10 +14,14 @@ THEME = 'default'
USE_LOCAL_COMMENT = True # if false, to include comment.html
-ACCEPT_LANGUAGES = ['en', 'zh']
+ACCEPT_LANGUAGES = ['en', 'de']
-BABEL_DEFAULT_LOCALE = 'zh'
-BABEL_DEFAULT_TIMEZONE = 'Asia/Shanghai'
+BABEL_DEFAULT_LOCALE = 'de'
+BABEL_DEFAULT_TIMEZONE = 'Europe/Berlin'
+
+RECAPTCHA_PUBLIC_KEY="your_public_key"
+RECAPTCHA_PRIVATE_KEY="your_private_key"
+RECAPTCHA_OPTIONS={'theme' : 'white'}
# http://twitter.com/oauth_clients/new
TWITTER_KEY = ''
@@ -28,13 +32,13 @@ PER_PAGE = 20
DEBUG_LOG = 'logs/debug.log'
ERROR_LOG = 'logs/error.log'
-ADMINS = ('yourname@domain.com',)
+ADMINS = ('admin@admin.com',)
MAIL_SERVER = 'smtp.gmail.com'
MAIL_PORT = 465
MAIL_USE_TLS = False
MAIL_USE_SSL = True
MAIL_DEBUG = DEBUG
-MAIL_USERNAME = 'username'
-MAIL_PASSWORD = 'password'
-DEFAULT_MAIL_SENDER = 'yourname@domain.com'
+MAIL_USERNAME = 'USER'
+MAIL_PASSWORD = 'PASSWORD'
+DEFAULT_MAIL_SENDER = 'admin@admin.com'
View
4 pypress/extensions.py
@@ -4,12 +4,12 @@
from flaskext.mail import Mail
from flaskext.sqlalchemy import SQLAlchemy
from flaskext.cache import Cache
-from flaskext.uploads import UploadSet, IMAGES
+from flaskext.uploads import UploadSet, AllExcept, EXECUTABLES, SCRIPTS
__all__ = ['mail', 'db', 'cache', 'photos']
mail = Mail()
db = SQLAlchemy()
cache = Cache()
-photos = UploadSet('photos', IMAGES)
+uploader = UploadSet('uploads', AllExcept(SCRIPTS + EXECUTABLES))
View
2  pypress/forms/__init__.py
@@ -1 +1 @@
-#!/usr/bin/env python
+#!/usr/bin/env python
View
39 pypress/forms/blog.py
@@ -7,10 +7,12 @@
:license: BSD, see LICENSE for more details.
"""
-from flaskext.wtf import Form, TextAreaField, SubmitField, TextField, \
- ValidationError, required, email, url, optional
+from flaskext.wtf import Form, TextAreaField, SubmitField, TextField, BooleanField, \
+ FileField, RecaptchaField, ValidationError, required, email, url, optional
-from flaskext.babel import gettext, lazy_gettext as _
+from flaskext.babel import gettext, lazy_gettext as _
+
+from recaptcha.client import captcha
from pypress.helpers import slugify
from pypress.extensions import db
@@ -25,11 +27,12 @@ class PostForm(Form):
content = TextAreaField(_("Content"))
- tags = TextField(_("Tags"), validators=[
- required(message=_("Tags required"))])
+ tags = TextField(_("Tags"))
submit = SubmitField(_("Save"))
+ page = BooleanField("Page")
+
def __init__(self, *args, **kwargs):
self.post = kwargs.get('obj', None)
super(PostForm, self).__init__(*args, **kwargs)
@@ -51,46 +54,52 @@ class CommentForm(Form):
email = TextField(_("Email"), validators=[
required(message=_("Email required")),
email(message=_("A valid email address is required"))])
-
+
nickname = TextField(_("Nickname"), validators=[
required(message=_("Nickname required"))])
-
+
website = TextField(_("Website"), validators=[
optional(),
url(message=_("A valid url is required"))])
-
+
comment = TextAreaField(_("Comment"), validators=[
required(message=_("Comment required"))])
-
+
+ recaptcha = RecaptchaField()
submit = SubmitField(_("Add comment"))
cancel = SubmitField(_("Cancel"))
-
class LinkForm(Form):
name = TextField(_("Site name"), validators=[
required(message=_("Name required"))])
-
+
link = TextField(_("link"), validators=[
url(message=_("A valid url is required"))])
-
+
email = TextField(_("Email"), validators=[
email(message=_("A valid email is required"))])
-
+
logo = TextField(_("Logo"), validators=[
optional(),
url(message=_("A valid url is required"))])
-
+
description = TextAreaField(_("Description"))
submit = SubmitField(_("Save"))
+class UploadForm(Form):
+
+ file = FileField(_("File"), validators=[
+ required(message=_("File required"))])
+
+ submit = SubmitField(_("Save"))
class TemplateForm(Form):
html = TextAreaField(_("HTML"), validators=[
required(message=_("HTML required"))])
-
+
submit = SubmitField(_("Save"))
cancel = SubmitField(_("Cancel"))
View
36 pypress/helpers.py
@@ -19,9 +19,11 @@
from pygments.lexers import get_lexer_by_name
from pygments.formatters import HtmlFormatter
+import genshi.builder as bldr
+
from flask import current_app, g
from flaskext.babel import gettext, ngettext, format_date, format_datetime
-from flaskext.themes import render_theme_template
+from flaskext.themes import render_theme_template
from pypress.extensions import cache
@@ -48,16 +50,16 @@ def __getattr__(self, key):
return self[key]
except KeyError, k:
raise AttributeError, k
-
+
def __setattr__(self, key, value):
self[key] = value
-
+
def __delattr__(self, key):
try:
del self[key]
except KeyError, k:
raise AttributeError, k
-
+
def __repr__(self):
return '<Storage ' + dict.__repr__(self) + '>'
@@ -80,6 +82,20 @@ def slugify(text, delim=u'-'):
safe_mode='remove',
output_format="html")
+def creole_make_img(match, environ):
+ dct = match.groupdict()
+ src = dct['src']
+ if 'width' in dct:
+ width = dct['width']
+ height = dct['height']
+ if 'alt' in dct:
+ alt = dct['alt']
+ return bldr.tag.img(src=src, width=width, height=height, alt=alt, title=alt)
+ else:
+ return bldr.tag.img(src=src, width=width, height=height)
+ return bldr.tag.img(src=src)
+
+
cached = functools.partial(cache.cached,
unless= lambda: g.user is not None)
@@ -90,7 +106,7 @@ def render_template(template, **context):
return render_theme_template(get_theme(), template, **context)
def request_wants_json(request):
- """
+ """
we only accept json if the quality of json is greater than the
quality of text/html because text/html is preferred to support
browsers that accept on */*
@@ -105,7 +121,7 @@ def timesince(dt, default=None):
Returns string representing "time since" e.g.
3 days ago, 5 hours ago etc.
"""
-
+
if default is None:
default = gettext("just now")
@@ -118,7 +134,7 @@ def timesince(dt, default=None):
days = diff.days
hours = diff.seconds / 3600
minutes = diff.seconds / 60
- seconds = diff.seconds
+ seconds = diff.seconds
periods = (
(years, ngettext("%(num)s year", "%(num)s years", num=years)),
@@ -169,7 +185,7 @@ def endtags(html):
closed_tags.remove(tag)
else:
html += "</%s>" % tag
-
+
return html
class Gravatar(object):
@@ -260,7 +276,7 @@ def code_highlight(value):
return u''.join(s_list)
return value
-
+
def code2html(code, lang):
lexer = get_lexer_by_name(lang, stripall=True)
formatter = HtmlFormatter()
@@ -271,4 +287,4 @@ def ip2long(ip):
def long2ip(num):
return socket.inet_ntoa(struct.pack("!I",num))
-
+
View
2  pypress/models/__init__.py
@@ -1 +1 @@
-#!/usr/bin/env python
+#!/usr/bin/env python
View
176 pypress/models/blog.py
@@ -37,7 +37,7 @@ def as_list(self):
Return restricted list of columns for list queries
"""
- deferred_cols = ("content",
+ deferred_cols = ("content",
"tags",
"author.email",
"author.activation_key",
@@ -47,13 +47,13 @@ def as_list(self):
options = [db.defer(col) for col in deferred_cols]
return self.options(*options)
-
+
def get_by_slug(self, slug):
post = self.filter(Post.slug==slug).first()
if post is None:
abort(404)
return post
-
+
def search(self, keywords):
criteria = []
@@ -66,70 +66,69 @@ def search(self, keywords):
))
q = reduce(db.and_, criteria)
- return self.filter(q)
+ return self.filter(q).order_by(Post.created_date)
def archive(self, year, month, day):
- if not year:
- return self
-
criteria = []
- criteria.append(db.extract('year',Post.created_date)==year)
+ criteria.append(Post._page == False)
+ if year: criteria.append(db.extract('year',Post.created_date)==year)
if month: criteria.append(db.extract('month',Post.created_date)==month)
if day: criteria.append(db.extract('day',Post.created_date)==day)
-
+
q = reduce(db.and_, criteria)
- return self.filter(q)
+ return self.filter(q).order_by(Post.created_date.desc())
class Post(db.Model):
__tablename__ = 'posts'
- PER_PAGE = 40
-
+ PER_PAGE = 10
+
query_class = PostQuery
-
+
id = db.Column(db.Integer, primary_key=True)
- author_id = db.Column(db.Integer,
- db.ForeignKey(User.id, ondelete='CASCADE'),
+ author_id = db.Column(db.Integer,
+ db.ForeignKey(User.id, ondelete='CASCADE'),
nullable=False)
-
+
_title = db.Column("title", db.Unicode(100), index=True)
_slug = db.Column("slug", db.Unicode(50), unique=True, index=True)
content = db.Column(db.UnicodeText)
num_comments = db.Column(db.Integer, default=0)
created_date = db.Column(db.DateTime, default=datetime.utcnow)
update_time = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
+ _page = db.Column(db.Boolean, default=False)
_tags = db.Column("tags", db.Unicode(100), index=True)
author = db.relation(User, innerjoin=True, lazy="joined")
__mapper_args__ = {'order_by': id.desc()}
-
+
class Permissions(object):
-
+
def __init__(self, obj):
self.obj = obj
@cached_property
def edit(self):
return Permission(UserNeed(self.obj.author_id))
-
+
@cached_property
def delete(self):
return Permission(UserNeed(self.obj.author_id)) & moderator
-
+
def __init__(self, *args, **kwargs):
super(Post, self).__init__(*args, **kwargs)
def __str__(self):
return self.title
-
+
def __repr__(self):
return "<%s>" % self
-
+
@cached_property
def permissions(self):
return self.Permissions(self)
@@ -143,7 +142,7 @@ def _set_title(self, title):
self.slug = slugify(title)[:50]
title = db.synonym("_title", descriptor=property(_get_title, _set_title))
-
+
def _get_slug(self):
return self._slug
@@ -152,12 +151,20 @@ def _set_slug(self, slug):
self._slug = slugify(slug)
slug = db.synonym("_slug", descriptor=property(_get_slug, _set_slug))
-
+
+ def _get_page(self):
+ return self._page
+
+ def _set_page(self, page):
+ self._page = page
+
+ page = db.synonym("_page", descriptor=property(_get_page, _set_page))
+
def _get_tags(self):
- return self._tags
+ return self._tags
def _set_tags(self, tags):
-
+
self._tags = tags
if self.id:
@@ -173,11 +180,11 @@ def _set_tags(self, tags):
if tag_obj is None:
tag_obj = Tag(name=tag, slug=slug)
db.session.add(tag_obj)
-
+
tag_obj.posts.append(self)
tags = db.synonym("_tags", descriptor=property(_get_tags, _set_tags))
-
+
@property
def taglist(self):
if self.tags is None:
@@ -189,32 +196,30 @@ def taglist(self):
@cached_property
def linked_taglist(self):
"""
- Returns the tags in the original order and format,
+ Returns the tags in the original order and format,
with link to tag page
"""
- return [(tag, url_for('frontend.tag',
+ return [(tag, url_for('frontend.tag',
slug=slugify(tag))) \
for tag in self.taglist]
-
+
@cached_property
def summary(self):
- s = re.findall(r'(<p id="more\-(\d+)">)', self.content)
+ s = re.findall(r'(----|\n\n\n|==)', self.content)
if not s:
return self.content
- p, more_id = s[0]
- addlink = '<p><a class="more-link" href="%s#more-%s">%s</a></p>' % (self.url, more_id, _("Read more..."))
- return self.content.split(p)[0] + addlink
-
+ return self.content.split(s[0])[0]
+
@cached_property
def comments(self):
"""
- Returns comments in tree. Each parent comment has a "comments"
+ Returns comments in tree. Each parent comment has a "comments"
attribute appended and a "depth" attribute.
"""
comments = Comment.query.filter(Comment.post_id==self.id).all()
def _get_comments(parent, depth):
-
+
parent.comments = []
parent.depth = depth
@@ -233,21 +238,23 @@ def _get_comments(parent, depth):
@cached_property
def json(self):
"""
- Returns dict of safe attributes for passing into
+ Returns dict of safe attributes for passing into
a JSON request.
"""
-
+
return dict(id=self.id,
title=self.title,
content=self.content,
author=self.author.username)
-
+
def _url(self, _external=False):
- return url_for('frontend.post',
+ if self._page:
+ return url_for('frontend.display', slug=self.slug)
+ return url_for('frontend.post',
year=self.created_date.year,
month=self.created_date.month,
day=self.created_date.day,
- slug=self.slug,
+ slug=self.slug,
_external=_external)
@cached_property
@@ -257,13 +264,12 @@ def url(self):
@cached_property
def permalink(self):
return self._url(True)
-
post_tags = db.Table("post_tags", db.Model.metadata,
- db.Column("post_id", db.Integer,
- db.ForeignKey('posts.id', ondelete='CASCADE'),
+ db.Column("post_id", db.Integer,
+ db.ForeignKey('posts.id', ondelete='CASCADE'),
primary_key=True),
- db.Column("tag_id", db.Integer,
+ db.Column("tag_id", db.Integer,
db.ForeignKey('tags.id', ondelete='CASCADE'),
primary_key=True))
@@ -286,18 +292,18 @@ def cloud(self):
for tag in tags:
tag.size = int(tag.num_posts / diff)
- if tag.size < 1:
+ if tag.size < 1:
tag.size = 1
random.shuffle(tags)
return tags
-
+
class Tag(db.Model):
__tablename__ = "tags"
-
+
query_class = TagQuery
id = db.Column(db.Integer, primary_key=True)
@@ -305,10 +311,10 @@ class Tag(db.Model):
posts = db.dynamic_loader(Post, secondary=post_tags, query_class=PostQuery)
_name = db.Column("name", db.Unicode(80), unique=True)
-
+
def __init__(self, *args, **kwargs):
super(Tag, self).__init__(*args, **kwargs)
-
+
def __str__(self):
return self.name
@@ -335,20 +341,20 @@ class Comment(db.Model):
__tablename__ = "comments"
- PER_PAGE = 40
-
+ PER_PAGE = 40
+
id = db.Column(db.Integer, primary_key=True)
- post_id = db.Column(db.Integer,
- db.ForeignKey(Post.id, ondelete='CASCADE'),
+ post_id = db.Column(db.Integer,
+ db.ForeignKey(Post.id, ondelete='CASCADE'),
nullable=False)
- author_id = db.Column(db.Integer,
- db.ForeignKey(User.id, ondelete='CASCADE'))
+ author_id = db.Column(db.Integer,
+ db.ForeignKey(User.id, ondelete='CASCADE'))
- parent_id = db.Column(db.Integer,
+ parent_id = db.Column(db.Integer,
db.ForeignKey("comments.id", ondelete='CASCADE'))
-
+
email = db.Column(db.String(50))
nickname = db.Column(db.Unicode(50))
website = db.Column(db.String(100))
@@ -365,12 +371,12 @@ class Comment(db.Model):
parent = db.relation('Comment', remote_side=[id])
__mapper_args__ = {'order_by' : id.asc()}
-
+
class Permissions(object):
-
+
def __init__(self, obj):
self.obj = obj
-
+
@cached_property
def reply(self):
return Permission(UserNeed(self.obj.post.author_id))
@@ -386,12 +392,12 @@ def __init__(self, *args, **kwargs):
@cached_property
def permissions(self):
return self.Permissions(self)
-
+
def _get_author(self):
if self._author:
return self._author
- return storage(email = self.email,
- nickname = self.nickname,
+ return storage(email = self.email,
+ nickname = self.nickname,
website = self.website)
def _set_author(self, author):
@@ -414,7 +420,6 @@ def permalink(self):
def markdown(self):
return Markup(markdown(self.comment or ''))
-
class Link(db.Model):
__tablename__ = "links"
@@ -429,12 +434,12 @@ class Link(db.Model):
email = db.Column(db.String(50))
passed = db.Column(db.Boolean, default=False)
created_date = db.Column(db.DateTime, default=datetime.utcnow)
-
+
class Permissions(object):
-
+
def __init__(self, obj):
self.obj = obj
-
+
@cached_property
def edit(self):
return moderator
@@ -449,10 +454,39 @@ def __init__(self, *args, **kwargs):
@cached_property
def permissions(self):
return self.Permissions(self)
-
+
def __str__(self):
return self.name
+class Upload(db.Model):
+
+ __tablename__ = "uploads"
+
+ PER_PAGE = 20
+
+ id = db.Column(db.Integer, primary_key=True)
+ file = db.Column(db.Unicode(250), nullable=False)
+ created_date = db.Column(db.DateTime, default=datetime.utcnow)
+
+ class Permissions(object):
+
+ def __init__(self, obj):
+ self.obj = obj
+
+ @cached_property
+ def delete(self):
+ return moderator
+
+ def __init__(self, *args, **kwargs):
+ super(Upload, self).__init__(*args, **kwargs)
+
+ @cached_property
+ def permissions(self):
+ return self.Permissions(self)
+
+ def __str__(self):
+ return self.file
+
# ------------- SIGNALS ----------------#
def update_num_comments(sender):
View
BIN  pypress/static/favicon.ico
Binary file not shown
View
63 pypress/static/js/public.js
@@ -1,45 +1,52 @@
var ajax_post = function(url, params, on_success){
- var _callback = function(response){
- if (response.success) {
- if (response.redirect_url){
- window.location.href = response.redirect_url;
- } else if (response.reload){
- window.location.reload();
- } else if (on_success) {
- return on_success(response);
- }
- } else {
- return message(response.error, "error");
- }
- }
-
- $.post(url, params, _callback, "json");
+ var _callback = function(response){
+ if (response.success) {
+ if (response.redirect_url){
+ window.location.href = response.redirect_url;
+ } else if (response.reload){
+ window.location.reload();
+ } else if (on_success) {
+ return on_success(response);
+ }
+ } else {
+ return message(response.error, "error");
+ }
+ }
+
+ $.post(url, params, _callback, "json");
}
var message = function(message, category){
- $('ul#messages').html('<li class="' + category + '">' + message + '</li>').fadeOut();
+ $('ul#messages').html('<li class="' + category + '">' + message + '</li>').fadeOut();
}
var delete_comment = function(url) {
- var callback = function(response){
- $('#comment-' + response.comment_id).fadeOut();
- }
- ajax_post(url, null, callback);
+ var callback = function(response){
+ $('#comment-' + response.comment_id).fadeOut();
+ }
+ ajax_post(url, null, callback);
}
var delete_link = function(url) {
- var callback = function(response){
- $('#link-' + response.link_id).fadeOut();
- }
- ajax_post(url, null, callback);
+ var callback = function(response){
+ $('#link-' + response.link_id).fadeOut();
+ }
+ ajax_post(url, null, callback);
+}
+
+var delete_upload = function(url) {
+ var callback = function(response){
+ $('#upload-' + response.upload_id).fadeOut();
+ }
+ ajax_post(url, null, callback);
}
var pass_link = function(url) {
- var callback = function(response){
- $('#link-' + response.link_id).find('.link-edit').remove();
- }
- ajax_post(url, null, callback);
+ var callback = function(response){
+ $('#link-' + response.link_id).find('.link-edit').remove();
+ }
+ ajax_post(url, null, callback);
}
var hide_flash = function(){
View
43 pypress/templates/account/login.html
@@ -1,33 +1,32 @@
{% extends theme("layout.html") %}
{% from "macros/_forms.html" import render_errors %}
+{% block js%}{% endblock %}
-{%- block content %}
+{% block content %}
<h2 class="title">{{ _('Login to pypress') }}</h2>
<div id="sign">
<form method="POST" action=".">
+ <fieldset>
{{ form.hidden_tag() }}
- <table cellspacing="0" class="form-table">
- <tbody>
- <tr>
- <th>{{ form.login.label }}</th>
- <td>{{ form.login(size=30) }} {{ render_errors(form.login) }}</td>
- </tr>
- <tr>
- <th>{{ form.password.label }}</th>
- <td>{{ form.password(size=30) }} {{ render_errors(form.password) }}</td>
- </tr>
- <tr>
- <th>{{ form.remember.label }}</th>
- <td>{{ form.remember }}</td>
- </tr>
- <tr>
- <th></th>
- <td>{{ form.submit }}</td>
- </tr>
+ <p>
+ {{ form.login.label }}
+ {{ form.login(size=30) }} {{ render_errors(form.login) }}
+ </p>
+ <p>
+ {{ form.password.label }}
+ {{ form.password(size=30) }} {{ render_errors(form.password) }}
+ </p>
+ <p>
+ {{ form.remember.label }}
+ {{ form.remember }}
+ </p>
+ <p>
+
+ {{ form.submit(class="formbutton") }}
+ </p>
</tbody>
</table>
+ </fieldset>
</form>
</div>
- <p><a href="{{ url_for('account.signup', next=form.next.data) }}">{{ _('Not a member yet ? Sign up !') }}</a></p>
-{%- endblock %}
-{%- block sidebar %}{%- endblock %}
+{% endblock %}
View
5 pypress/templates/account/signup.html
@@ -1,7 +1,7 @@
{% extends theme("layout.html") %}
{% from "macros/_forms.html" import render_errors %}
-{%- block content %}
+{% block content %}
<h2 class="title">{{ _('Sign up to pypress') }}</h2>
<div id="sign">
<form method="POST" action=".">
@@ -40,5 +40,4 @@ <h2 class="title">{{ _('Sign up to pypress') }}</h2>
</table>
</form>
</div>
-{%- endblock %}
-{%- block sidebar %}{%- endblock %}
+{% endblock %}
View
7 pypress/templates/blog/_archive.html
@@ -1,10 +1,9 @@
<div id="archives" class="sidebox">
- <h3>{{ _("Archive") }}</h3>
+ <h4>{{ _("Archive") }}</h4>
<div class="inner">
{% if archives %}
- <ul>
- {% for date in archives %}
- <li><a href="{{ url_for('frontend.index',year=date.year,month=date.month) }}">{{ date|format_date('yyyy\u5e74MMMM') }}</a></li>
+ {% for date in archives[:10] %}
+ <div class="news-item"><a href="{{ url_for('frontend.index',year=date.year,month=date.month) }}">{{ date|format_date('MMMM yyyy') }}</a></div>
{% endfor %}
</ul>
{% endif %}
View
1  pypress/templates/blog/_comment.html
@@ -1,3 +1,4 @@
+
<div id="comment" class="sidebox">
<h3>{{ _("Latest Comments") }}</h3>
<div class="inner">
View
3  pypress/templates/blog/_postnow.html
@@ -1,3 +1,4 @@
{% if g.user %}
-<div id="postnow"><input type="button" value="{{ _("Post Now") }}" class="button" onclick="location.href='{{ url_for('post.submit') }}'" /></div>
+<form><div id="postnow"><input type="button" value="{{ _("Post Now") }}" class="formbutton" onclick="location.href='{{ url_for('post.submit') }}'" /></div>
+</form>
{% endif %}
View
8 pypress/templates/blog/_search.html
@@ -1,8 +1,8 @@
<div id="search" class="sidebox">
- <form action="{{ url_for('frontend.search') }}" id="searchform" method="get">
+ <h4>Search</h4>
<div class="inner">
- <p><label for="q">{{ _("Search all posts") }}:</label></p>
- <input type="text" class="text" value="{{ request.args.get('q','') }}" id="q" name="q"><input type="submit" class="button" value="{{ _('Search') }}" id="searchsubmit">
- </div>
+ <form action="{{ url_for('frontend.search') }}" id="searchform" class="searchform" method="get">
+ <input type="text" class="text" value="{{ request.args.get('q','') }}" id="q" name="q"><input type="submit" class="formbutton" value="{{ _('Search') }}" id="searchsubmit">
</form>
+ </div>
</div>
View
2  pypress/templates/blog/_tags.html
@@ -1,5 +1,5 @@
<div id="tags" class="sidebox">
- <h3>{{ _("Tags") }}</h3>
+ <h4>{{ _("Tags") }}</h4>
<div class="inner">
{% if tags %}
<ul>
View
40 pypress/templates/blog/add_comment.html
@@ -11,36 +11,26 @@ <h2 class="title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
{%- endif %}
<div id="add_comment">
<form method="post" action=".">
+ <fieldset>
{{ form.hidden_tag() }}
- <table cellspacing="0" class="form-table">
- <tbody>
{%- if g.user %}
{{ form.email(type='hidden',value=g.user.email) }}
{{ form.nickname(type='hidden',value=g.user.nickname) }}
- {%- else %}
- <tr>
- <th>{{ form.email.label }}</th>
- <td>{{ form.email(size=50, class="text") }} {{ render_errors(form.email) }}</td>
- </tr>
- <tr>
- <th>{{ form.nickname.label }}</th>
- <td>{{ form.nickname(size=50, class="text") }} {{ render_errors(form.nickname) }}</td>
- </tr>
- <tr>
- <th>{{ form.website.label }}</th>
- <td>{{ form.website(size=50, class="text") }} {{ render_errors(form.website) }}</td>
- </tr>
- <tr>
- <th>{{ form.comment.label }}</th>
- <td>{{ form.comment(class="text", style="width:400px;height:100px;") }} {{ render_errors(form.comment) }}</td>
- </tr>
- <tr>
- <th></th>
- <td>{{ form.submit(class="button") }}</td>
- </tr>
+ {%- else %}
+ <p>{{ form.email.label }}
+ {{ form.email(size=50, class="text") }} {{ render_errors(form.email) }}</p>
+ <p>{{ form.nickname.label }}
+ {{ form.nickname(size=50, class="text") }} {{ render_errors(form.nickname) }}</p>
+ <p>{{ form.website.label }}
+ {{ form.website(size=50, class="text") }} {{ render_errors(form.website) }}</p>
{%- endif %}
- </tbody>
- </table>
+ <p>{{ form.comment.label }}
+ {{ form.comment }} {{ render_errors(form.comment) }}</p>
+ {% if not g.user %}
+ {{ form.recaptcha }}
+ {% endif %}
+ {{ form.submit(class="formbutton") }}
+ </fieldset>
</form>
</div>
</div>
View
54 pypress/templates/blog/add_link.html
@@ -7,35 +7,33 @@
<h2 class="title">{{ _("Add link") }}</h2>
<div id="add_link">
<form method="POST" action=".">
+ <fieldset>
{{ form.hidden_tag() }}
- <table cellspacing="0" class="form-table">
- <tbody>
- <tr>
- <th>{{ form.name.label }}</th>
- <td>{{ form.name(size=30, class="text") }} {{ render_errors(form.name) }}</td>
- </tr>
- <tr>
- <th>{{ form.link.label }}</th>
- <td>{{ form.link(size=50, class="text") }} {{ render_errors(form.link) }}</td>
- </tr>
- <tr>
- <th>{{ form.email.label }}</th>
- <td>{{ form.email(size=50, class="text") }} {{ render_errors(form.email) }}</td>
- </tr>
- <tr>
- <th>{{ form.logo.label }}</th>
- <td>{{ form.logo(size=50, class="text") }} {{ render_errors(form.logo) }}</td>
- </tr>
- <tr>
- <th>{{ form.description.label }}</th>
- <td>{{ form.description(class="text", style="width:400px;height:100px;") }} {{ render_errors(form.description) }}</td>
- </tr>
- <tr>
- <th></th>
- <td>{{ form.submit(class="button") }}</td>
- </tr>
- </tbody>
- </table>
+ <p>
+ {{ form.name.label }}
+ {{ form.name(size=30, class="text") }} {{ render_errors(form.name) }}
+ </p>
+ <p>
+ {{ form.link.label }}
+ {{ form.link(size=50, class="text") }} {{ render_errors(form.link) }}
+ </p>
+ <p>
+ {{ form.email.label }}
+ {{ form.email(size=50, class="text") }} {{ render_errors(form.email) }}
+ </p>
+ <p>
+ {{ form.logo.label }}
+ {{ form.logo(size=50, class="text") }} {{ render_errors(form.logo) }}
+ </p>
+ <p>
+ {{ form.description.label }}
+ {{ form.description(class="text", style="width:400px;height:100px;") }} {{ render_errors(form.description) }}
+ </p>
+ <p>
+
+ {{ form.submit(class="formbutton") }}
+ </p>
+ </fieldset>
</form>
</div>
</div>
View
22 pypress/templates/blog/add_upload.html
@@ -0,0 +1,22 @@
+{% extends theme("layout.html") %}
+
+{% from "macros/_forms.html" import render_errors %}
+
+{%- block content %}
+<div class="content">
+ <h2 class="title">{{ _("Upload") }}</h2>
+ <div id="add_upload">
+ <form method="POST" action="." enctype="multipart/form-data">
+ <fieldset>
+ {{ form.hidden_tag() }}
+ <p>
+ {{ form.file.label }}
+ {{ form.file }} {{ render_errors(form.file) }}
+ </p>
+ {{ form.submit(class="formbutton") }}
+ </p>
+ </fieldset>
+ </form>
+ </div>
+</div>
+{%- endblock %}
View
12 pypress/templates/blog/archive.html
@@ -8,19 +8,9 @@ <h2 class="title">{{ _("Archive") }}</h2>
<div id="archive">
<ul>
{%- for date in archives %}
- <li><a href="{{ url_for('frontend.index',year=date.year,month=date.month) }}">{{ date|format_date('yyyy\u5e74MMMM') }}</a></li>
+ <li><a href="{{ url_for('frontend.index',year=date.year,month=date.month) }}">{{ date|format_date('MMMM yyyy') }}</a></li>
{%- endfor %}
</ul>
</div>
</div>
{%- endblock %}
-{%- block sidebar %}
-<div class="sidebar">
- {% include "blog/_postnow.html" %}
- {% include "blog/_search.html" %}
- {% include "blog/_tags.html" %}
- {% include "blog/_comment.html" %}
- {% include "blog/_archive.html" %}
- {% include "blog/_links.html" %}
-</div>
-{%- endblock %}
View
18 pypress/templates/blog/list.html
@@ -7,16 +7,16 @@
{%- if page_obj.items %}
{%- for post in page_obj.items %}
<div id="post-{{ post.id }}" class="post">
- <div class="post-avatar"><a href="{{ url_for('frontend.people', username=post.author.username) }}"><img src="{{ post.author.email|gravatar(size=50) }}" alt="{{ post.author.nickname }}" /></a></div>
<h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
<div class="post-byline">
- By <a href="{{ url_for('frontend.people', username=post.author.username) }}">{{ post.author.nickname }}</a>. <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|timesince }}</abbr>
+ <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|format_date('medium') }}</abbr>
</div>
{% if post.tags %}<div class="post-tags">{% for tag,url in
post.linked_taglist %}<a href="{{ url }}">{{ tag }}</a>{{ ', ' if not
loop.last }}{% endfor %}</div>{% endif %}
<div class="post-summary">
- {{ post.summary|endtags|code_highlight|safe }}
+{# {{ post.summary|endtags|code_highlight|safe }}#}
+ {{ post.summary|creolify|code_highlight|safe }}
</div>
<div class="post-info"><img alt="comment" src="{{ theme_static('comment.gif') }}"> <span class="post-comments"><a href="{{ post.url }}#comments">{{ post.num_comments }} comments</a></span></div>
{%- if post.update_date %}
@@ -30,15 +30,9 @@ <h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
{%- else %}
<p>{{ _("Nobody's posted anything yet.") }}</p>
{%- endif %}
+<div class="inner">All the bloggy goodness:
+<a href="/tags/">All tags</a>
+<a href="/feeds/">RSS feed</a>
</div>
-{%- endblock %}
-{%- block sidebar %}
-<div class="sidebar">
- {% include "blog/_postnow.html" %}
- {% include "blog/_search.html" %}
- {% include "blog/_tags.html" %}
- {% include "blog/_comment.html" %}
- {% include "blog/_archive.html" %}
- {% include "blog/_links.html" %}
</div>
{%- endblock %}
View
22 pypress/templates/blog/page.html
@@ -0,0 +1,22 @@
+{% extends theme("layout.html") %}
+
+{% block content %}
+<div class="content">
+ <div class="post-content">
+ {{ post.content|creolify|code_highlight|safe }}
+ </div>
+ {%- if post.permissions.edit %}
+ | <a href="{{ url_for('post.edit', post_id=post.id) }}">{{ _("edit this post") }}</a>
+ {%- endif %}
+ {%- if post.permissions.delete %}
+ | <a href="#" onclick="$('#delete-post').toggle(); return false;">{{ _("delete this post") }}</a>
+ <div id="delete-post" style="display:none;">
+ <strong>{{ _('Are you sure you want to delete this post ?') }}</strong>
+ <a href="#" onclick="ajax_post('{{ url_for('post.delete', post_id=post.id) }}'); return false;">{{ _('yes') }}</a> /
+ <a href="#" onclick="$('#delete-post').toggle(); return false;">{{ _('no') }}</a>
+ </div>
+ {%- endif %}
+
+
+</div>
+{% endblock %}
View
12 pypress/templates/blog/people.html
@@ -6,7 +6,6 @@
{%- block content %}
<div class="content">
<div id="user">
- <div class="avatar"><img src="{{ people.email|gravatar(size=50) }}" alt="{{ people.nickname }}" /></div>
<div class="info">
<h3>{{ people.nickname }}</h3>
<p>{{ _("Joined in") }}:{{ people.date_joined }}</p>
@@ -42,7 +41,7 @@ <h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
</div>
{%- endfor %}
{{ paginate(page_obj, page_url) }}
- {%- else %}
+ {%- else %}
{%- if g.user == people %}
<p>{{ _("You has not posted anything yet.") }} <a href="{{ url_for('post.submit') }}">{{ _("Submit") }}</a></p>
{%- else %}
@@ -56,15 +55,6 @@ <h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
</div>
</div>
{%- endblock %}
-{%- block sidebar %}
-<div class="sidebar">
- {% include "blog/_postnow.html" %}
- {% include "blog/_search.html" %}
- {% include "blog/_tags.html" %}
- {% include "blog/_archive.html" %}
- {% include "blog/_links.html" %}
-</div>
-{%- endblock %}
{%- block js %}
{{ super() }}
<script type="text/javascript" src="{{ url_for('.static', filename="js/jquery.idTabs.min.js") }}"></script>
View
6 pypress/templates/blog/search_result.html
@@ -10,15 +10,15 @@ <h2 class="title">{{ _("Search results for") }} {{ request.args.get('q','') }}</
<div id="post-{{ post.id }}" class="post">
<h2 class="post-title"><a href="{{ post.url }}">{{ post.title }}</a></h2>
<div class="post-byline">
- By <a href="{{ url_for('frontend.people', username=post.author.username) }}">{{ post.author.nickname }}</a>. <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|timesince }}</abbr>
+ <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|timesince }}</abbr>
{% if post.tags %} | {% for tag,url in post.linked_taglist %}<a href="{{ url }}">{{ tag }}</a>{{ loop.last and '...' or ',' }}{% endfor %}{% endif %}
</div>
</div>
{%- endfor %}
{{ paginate(page_obj, page_url) }}
-{%- else %}
+{%- else %}
<h2 class="title error">{{ _("No posts found. Try a different search.") }} </h2>
{%- endif %}
</div>
{%- endblock %}
-
+
View
138 pypress/templates/blog/submit.html
@@ -5,119 +5,35 @@
{%- block content %}
<div class="single">
<h2 class="title">{{ _('Submit a post') }}</h2>
+ Would you like to <a href="{{url_for('uploads.add')}}">upload a file?</a>
+ Or <a href="{{url_for('uploads.index')}}">see all uploads?</a>
<form method="POST" action=".">
+ <fieldset>
{{ form.hidden_tag() }}
- <table cellspacing="0" class="post-form">
- <tbody>
- <tr>
- <th>{{ form.title.label(style="display:block;width:100px;") }}</th>
- <td>{{ form.title(size=50, class="text") }} {{ render_errors(form.title) }}</td>
- </tr>
- <tr>
- <th>{{ form.slug.label }}</th>
- <td>{{ form.slug(size=50, class="text") }} {{ render_errors(form.slug) }}</td>
- </tr>
- <tr>
- <th>{{ form.content.label }}</th>
- <td>{{ form.content(style="width:820px;height:400px;") }} {{ render_errors(form.content) }}</td>
- </tr>
- <tr>
- <th>{{ form.tags.label }}</th>
- <td>{{ form.tags(size=50, class="text") }} {{ render_errors(form.tags) }}</td>
- </tr>
- <tr>
- <th></th>
- <td>{{ form.submit(class="button") }}</td>
- </tr>
- </tbody>
- </table>
+ <p>{{ form.title.label }}
+ {{ form.title }} {{ render_errors(form.title) }}
+ </p>
+ <p>
+ {{ form.slug.label }}
+ {{ form.slug }} {{ render_errors(form.slug) }}
+ </p>
+ <p>
+ {{ form.tags.label }}
+ {{ form.tags }} {{ render_errors(form.tags) }}
+ </p>
+ <p>
+ {{ form.page.label }}
+ {{ form.page }} {{ render_errors(form.page) }}
+ </p>
+ <p>
+ {{ form.content.label }}
+ {{ form.content(style="width:590px;height:300px") }} {{ render_errors(form.content) }}
+ </p>
+ <div class="clear"/>
+ {{ form.submit(class="formbutton") }}
+ </fieldset>
</form>
</div>
-{%- endblock %}
-{%- block css %}
-{{ super() }}
-<!--[if lt IE 8]>
-<link href="http://a.tbcdn.cn/s/kissy/1.1.7/editor/theme/cool/editor-pkg-min-mhtml.css" rel="stylesheet"/>
-<![endif]-->
-<!--[if gte IE 8]><!-->
-<link href="http://a.tbcdn.cn/s/kissy/1.1.7/editor/theme/cool/editor-pkg-min-datauri.css" rel="stylesheet"/>
-<!--<![endif]-->
-{%- endblock %}
-{%- block js %}
-{{ super() }}
-<script src="http://a.tbcdn.cn/s/kissy/1.1.7/??kissy-min.js,uibase/uibase-pkg-min.js,dd/dd-pkg-min.js,overlay/overlay-pkg-min.js,editor/editor-all-pkg-min.js"></script>
-<script type="text/javascript">
-KISSY.ready(function(S){
- var KE = KISSY.Editor;
- var k = KE("#content",{
- "attachForm":true,
- "baseZIndex":1000,
- customStyle:"pre{padding:5px;font-size:12px;font-family:'Courier';border:1px solid #ccc;background:#eee;} p{margin:0.85em 0;line-height:1.8em;}",
- pluginConfig: {
- "templates": [{
- demo: "python code",
- html: '<pre l="python">#Copy here...\n</pre>'},
- {
- demo: "html code",
- html: '<pre l="html">\n\n</pre>'},
- {
- demo: "More",
- html: '<p id="more-1'+Math.round(Math.random()*1000)+'"></p>'}
- ],
- "image":{
- upload:{
- //success: {"imgUrl":"http://xx.com/yy.jpg"}
- //error: {"error":"i am error!"}
- serverUrl:"{{ url_for('frontend.upload') }}",
- serverParams:{},
- suffix: "png,jpg,jpeg,gif",
- fileInput:"Filedata"
- }
- },
- "font-size":{
- items:[{
- value:"14px",
- attrs:{
- style:'position: relative; border: 1px solid #DDDDDD; margin: 2px; padding: 2px;'
- },
- name:"" +
- " <span style='font-size:14px'>{{_('Normal')}}</span>" +
- "<span style='position:absolute;top:1px;right:3px;'>14px</span>"
- },
- {
- value:"16px",
- attrs:{
- style:'position: relative; border: 1px solid #DDDDDD; margin: 2px; padding: 2px;'
- },
- name:"" +
- " <span style='font-size:16px'>{{ _('Large') }}</span>" +
- "<span style='position:absolute;top:1px;right:3px;'>16px</span>"
- },
- {
- value:"20px",
- attrs:{
- style:'position: relative; border: 1px solid #DDDDDD; margin: 2px; padding: 2px;'
- },
- name:"" +
- " <span style='font-size:20px'>{{ _('Maximum') }}</span>" +
- "<span style='position:absolute;top:1px;right:3px;'>20px</span>"
- }],
- width:"115px"
- },
- "draft":{
- interval:5,
- limit:3
- }
- }
-
- }).use("elementpaths,sourcearea,preview,separator," +
- "undo,separator,removeformat,font,format,color,separator," +
- "list,indent,justify,separator,link,image,flash,music,smiley," +
- "separator,table,templates,pagebreak,resize,draft,separator,maximize"
- );
-
-});
-</script>
-{%- endblock %}
-{%- block sidebar %}{%- endblock %}
+{% endblock %}
+{% block js %}{% endblock %}
View
12 pypress/templates/blog/tags.html
@@ -14,14 +14,4 @@ <h2 class="title">{{ _("Tags") }}</h2>
</div>
</div>
{%- endblock %}
-{%- block sidebar %}
-<div class="sidebar">
- {% include "blog/_postnow.html" %}
- {% include "blog/_search.html" %}
- {% include "blog/_tags.html" %}
- {% include "blog/_comment.html" %}
- {% include "blog/_archive.html" %}
- {% include "blog/_links.html" %}
-</div>
-{%- endblock %}
-
+
View
31 pypress/templates/blog/uploads.html
@@ -0,0 +1,31 @@
+{% extends theme("layout.html") %}
+
+{% from "macros/_page.html" import paginate %}
+
+{%- block content %}
+<div class="content">
+ <h2 class="title">{{ _("Uploads") }}</h2>
+ <a href="{{url_for('uploads.add')}}">Upload another file?</a>
+ <div id="uploads">
+ <ul>
+ {%- for upload in page_obj.items %}
+ <li id="upload-{{ upload.id }}">{{ upload.file }} uploaded at {{upload.created_date|format_date('full')}}
+ <img src="/static/uploads/{{upload.file}}"/>
+ <span>
+ {%- if upload.permissions.delete %}
+ <a href="#" onclick="$('#delete-upload-{{ upload.id }}').toggle(); return false;" class="upload-delete">{{ _("delete") }}</a>
+ <div id="delete-upload-{{ upload.id }}" style="display:none;">
+ <strong>{{ _("Are you sure you want to delete this upload ?") }} </strong>
+ <a href="#" onclick="delete_upload('{{ url_for('uploads.delete', upload_id=upload.id) }}'); return false;">{{ _("yes") }}</a> /
+ <a href="#" onclick="$('#delete-upload-{{ upload.id }}').toggle(); return false;">{{ _("no") }}</a>
+ </div>
+ {%- endif %}
+ </span>
+ </li>
+ {%- endfor %}
+ </ul>
+ {{ paginate(page_obj, page_url) }}
+ </div>
+</div>
+{%- endblock %}
+
View
47 pypress/templates/blog/view.html
@@ -6,36 +6,35 @@
{%- block content %}
<div class="content">
<div id="post-{{ post.id }}" class="post">
- <div class="post-avatar"><a href="{{ url_for('frontend.people', username=post.author.username) }}"><img src="{{ post.author.email|gravatar(size=50) }}" alt="{{ post.author.nickname }}" /></a></div>
<h2 class="post-title">{{ post.title }}</h2>
<div class="post-byline">
- By <a href="{{ url_for('frontend.people', username=post.author.username) }}">{{ post.author.nickname }}</a>. <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|timesince }}</abbr>
+ <abbr title="{{ post.created_date|format_date('full') }}" class="time">{{ post.created_date|format_date('full') }}</abbr>
</div>
{% if post.tags %}<div class="post-tags">{% for tag,url in
post.linked_taglist %}<a href="{{ url }}">{{ tag }}</a>{{ ', ' if not loop.last }}{% endfor %}</div>{% endif %}
<div class="post-content">
- {{ post.content|code_highlight|gistcode|safe }}
+ {{ post.content|creolify|code_highlight|safe }}
</div>
<div class="post-meta">
{% if post.update_time %}<span class="post-time">{{ _("Modified at ") }}{{ post.update_time|format_date('full') }}</span> | {% endif %}<span class="post-tags">{% for tag,url in post.linked_taglist %}<a href="{{ url }}">{{ tag }}</a> {% endfor %}</span>
{%- if post.permissions.edit %}
- | <a href="{{ url_for('post.edit', post_id=post.id) }}">{{ _("edit this post") }}</a>
+ | <a href="{{ url_for('post.edit', post_id=post.id) }}">{{ _("edit this post") }}</a>
{%- endif %}
{%- if post.permissions.delete %}
- | <a href="#" onclick="$('#delete-post').toggle(); return false;">{{ _("delete this post") }}</a>
+ | <a href="#" onclick="$('#delete-post').toggle(); return false;">{{ _("delete this post") }}</a>
<div id="delete-post" style="display:none;">
<strong>{{ _('Are you sure you want to delete this post ?') }}</strong>
- <a href="#" onclick="ajax_post('{{ url_for('post.delete', post_id=post.id) }}'); return false;">{{ _('yes') }}</a> /
+ <a href="#" onclick="ajax_post('{{ url_for('post.delete', post_id=post.id) }}'); return false;">{{ _('yes') }}</a> /
<a href="#" onclick="$('#delete-post').toggle(); return false;">{{ _('no') }}</a>
</div>
{%- endif %}
</div>
</div>
-
+
<div class="navigation-links">
- <span class="previous">{% if prev_post %}&laquo; <a rel="prev" href="{{ prev_post.url }}">{{ prev_post.title }}</a>{% endif %}</span>
+ <span class="previous">{% if prev_post %}&laquo; <a rel="prev" href="{{ prev_post.url }}">{{ prev_post.title }}</a>{% endif %}</span>
<span class="next">{% if next_post %}<a rel="next" href="{{ next_post.url }}">{{ next_post.title }}</a> &raquo;{% endif %}</span>
</div>
@@ -44,18 +43,23 @@ <h2 class="post-title">{{ post.title }}</h2>
<div class="comment-add">
<h3>{{ _('Add a comment') }}</h3>
<form id="comment-form" method="POST" action="{{ url_for('post.add_comment', post_id=post.id) }}">
+ <fieldset>
{{ comment_form.hidden_tag() }}
{%- if g.user %}
{{ comment_form.email(type='hidden',value=g.user.email) }}
{{ comment_form.nickname(type='hidden',value=g.user.nickname) }}
{{ comment_form.website(type='hidden') }}
- {%- else %}
- <p>{{ comment_form.email(class="text") }} {{ comment_form.email.label }}</p>
- <p>{{ comment_form.nickname(class="text") }} {{ comment_form.nickname.label }}</p>
- <p>{{ comment_form.website(class="text") }} {{ comment_form.website.label }}</p>
+ {%- else %}
+ <p>{{ comment_form.email }} {{ comment_form.email.label }}</p>
+ <p>{{ comment_form.nickname }} {{ comment_form.nickname.label }}</p>
+ <p>{{ comment_form.website }} {{ comment_form.website.label }}</p>
{%- endif %}
- <p>{{ comment_form.comment(class="text") }}</p>
- <p>{{ comment_form.submit(class="button") }}</p>
+ <p>{{ comment_form.comment}} {{ comment_form.comment.label }}</p>
+ {% if not g.user %}
+ {{ comment_form.recaptcha }}
+ {% endif %}
+ <p>{{ comment_form.submit(class="formbutton") }}</p>
+ </fieldset>
</form>
</div>
@@ -66,12 +70,12 @@ <h2 class="post-title">{{ post.title }}</h2>
{%- for comment in post.comments %}
{{ render_comment(comment) }}
{%- endfor %}
- </ol>
+ </ol>
{%- else %}
<p>{{ _('No comments have been posted yet.') }}</p>
{%- endif %}
</div>
-
+
</div>
{%- else %}
{% include 'blog/comment.html' %}
@@ -79,17 +83,6 @@ <h2 class="post-title">{{ post.title }}</h2>
</div>
{%- endblock %}
-{%- block sidebar %}
-<div class="sidebar">
- {% include "blog/_postnow.html" %}
- {% include "blog/_search.html" %}
- {% include "blog/_tags.html" %}
- {% include "blog/_comment.html" %}
- {% include "blog/_archive.html" %}
- {% include "blog/_links.html" %}
-</div>
-{%- endblock %}
-
{%- block js %}
{{ super() }}
<script type="text/javascript">
View
1  pypress/templates/errors/403.html
@@ -12,7 +12,6 @@