-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Mikko Lehtinen
committed
Sep 25, 2010
0 parents
commit 708f748
Showing
952 changed files
with
115,483 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
About | ||
===== | ||
This is a blogging engine based on [[Bloggart-tipfy|http://github.com/mikkolehtinen/bloggart-tipfy]] | ||
|
||
Installation | ||
--------------------------- | ||
@git clone git@github.com:mikkolehtinen/mikkolehtinen.com.git@ | ||
@git submodule init && git submodule update@ | ||
|
||
- In your project folder run: | ||
python bootstrap.py --distribute | ||
bin/buildout | ||
|
||
- Start the development server calling bin/dev_appserver. It will use the | ||
application from /app by default: | ||
|
||
bin/dev_appserver | ||
|
||
- Open a browser and test the URLs: | ||
|
||
http://localhost:8080/ | ||
http://localhost:8080/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
application: myappid | ||
version: 1 | ||
runtime: python | ||
api_version: 1 | ||
|
||
derived_file_type: | ||
- python_precompiled | ||
|
||
handlers: | ||
|
||
- url: /remote_api | ||
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py | ||
login: admin | ||
|
||
- url: /_ah/queue/deferred | ||
script: main.py | ||
login: admin | ||
|
||
- url: /admin/static | ||
static_dir: templates/admin/static/ | ||
|
||
- url: /static/([^/]+)/(.*) | ||
static_files: templates/themes/\1/static/\2 | ||
upload: templates/themes/[^/]+/static/.* | ||
|
||
- url: /.* | ||
script: main.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
import os | ||
DEV_SERVER = os.environ.get('SERVER_SOFTWARE', '').startswith('Development/') | ||
DEBUG = TEMPLATE_DEBUG = DEV_SERVER | ||
|
||
# Name of the blog | ||
blog_name = 'mikkolehtinen.com' | ||
|
||
# Your name (used for copyright info) | ||
author_name = 'Mikko Lehtinen' | ||
|
||
# (Optional) slogan | ||
slogan = 'This is my blog' | ||
|
||
# The hostname this site will primarially serve off (used for Atom feeds) | ||
host = 'http://www.mikkolehtinen.com' | ||
|
||
# Selects the theme to use. Theme names correspond to directories under | ||
# the 'themes' directory, containing templates and static content. | ||
theme = 'mikkolehtinen' | ||
|
||
# Defines the URL organization to use for blog postings. Valid substitutions: | ||
# slug - the identifier for the post, derived from the title | ||
# year - the year the post was published in | ||
# month - the month the post was published in | ||
# day - the day the post was published in | ||
post_path_format = '/%(year)d/%(month)02d/%(slug)s' | ||
|
||
# A nested list of sidebar menus, for convenience. If this isn't versatile | ||
# enough, you can edit themes/default/base.html instead. | ||
sidebars = [ | ||
('Menu', [ | ||
]), | ||
] | ||
|
||
# Number of entries per page in indexes. | ||
posts_per_page = 5 | ||
|
||
# The mime type to serve HTML files as. | ||
html_mime_type = "text/html; charset=utf-8" | ||
|
||
# To use disqus for comments, set this to the 'short name' of the disqus forum | ||
# created for the purpose. | ||
disqus_forum = 'mikkolehtinen' | ||
|
||
# Length (in words) of summaries, by default | ||
summary_length = 200 | ||
|
||
# If you want to use Google Analytics, enter your 'web property id' here | ||
analytics_id = None | ||
|
||
# If you want to use PubSubHubbub, supply the hub URL to use here. | ||
hubbub_hub_url = 'http://pubsubhubbub.appspot.com/' | ||
|
||
# If you want to ping Google Sitemap when your sitemap is generated change this to True, else False | ||
# see: http://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=34609 for more information | ||
google_sitemap_ping = False | ||
|
||
# If you want to use Google Site verification, go to | ||
# https://www.google.com/webmasters/tools/ , add your site, choose the 'upload | ||
# an html file' method, then set the NAME of the file below. | ||
# Note that you do not need to download the file provided - just enter its name | ||
# here. | ||
google_site_verification = None | ||
|
||
# Default markup language for entry bodies (defaults to html). | ||
default_markup = 'html' | ||
|
||
# Syntax highlighting style for RestructuredText and Markdown, | ||
# one of 'manni', 'perldoc', 'borland', 'colorful', 'default', 'murphy', | ||
# 'vs', 'trac', 'tango', 'fruity', 'autumn', 'bw', 'emacs', 'pastie', | ||
# 'friendly', 'native'. | ||
highlighting_style = 'friendly' | ||
|
||
# Absolute url of the blog application use '/blog' for host/blog/ | ||
# and '' for host/.Also remember to change app.yaml accordingly | ||
url_prefix = '' | ||
|
||
# Defines where the user is defined in the rel="me" of your pages. | ||
# This allows you to expand on your social graph. | ||
rel_me = None | ||
|
||
# For use a feed proxy like feedburne.google.com | ||
feed_proxy = None | ||
|
||
# To use Google Friends Connect. | ||
# If you want use Google Friends Connect, go to http://www.google.com/friendconnect/ | ||
# and register your domain for get a Google Friends connect ID. | ||
google_friends_id = None | ||
google_friends_comments = True # For comments. | ||
google_friends_members = True # For a members container. | ||
|
||
# To format the date of your post. | ||
date_format = "%A %d. %B %Y" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from tipfy.ext.jinja2 import create_jinja2_instance | ||
|
||
def datetimeformat(value, format='%H:%M / %d-%m-%Y'): | ||
return value.strftime(format) | ||
|
||
def to_int(value): | ||
return int(value) | ||
|
||
def create_environment(): | ||
env = create_jinja2_instance() | ||
env.filters['datetimeformat'] = datetimeformat | ||
env.filters['to_int'] = to_int | ||
return env |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import logging | ||
from tipfy.ext.wtforms import Form, fields | ||
from ..models import BlogPost | ||
from wtforms.ext.appengine.db import ModelConverter, model_form | ||
|
||
class SetPropertyField(fields.TextAreaField): | ||
""" | ||
A field for ``db.SetProperty``. The set items are rendered in a | ||
textarea. | ||
""" | ||
def process_data(self, value): | ||
if isinstance(value, set): | ||
value = '\n'.join(value) | ||
self.data = value | ||
|
||
def populate_obj(self, obj, name): | ||
if isinstance(self.data, basestring): | ||
value = set(self.data.strip().splitlines()) | ||
else: | ||
value = set() | ||
setattr(obj, name, value) | ||
|
||
|
||
class BlogModelConverter(ModelConverter): | ||
""" | ||
Extends ModelConverter to support aetycoon's SetProperty | ||
""" | ||
def __init__(self, converters=None): | ||
self.extended_converters = self.default_converters | ||
self.extended_converters['SetProperty'] = convert_SetProperty | ||
self.converters = converters or self.extended_converters | ||
|
||
def convert_SetProperty(model, prop, kwargs): | ||
return SetPropertyField(**kwargs) | ||
|
||
class BasePostForm(Form): | ||
# Add an extra, non-model related field. | ||
draft = fields.BooleanField('Draft?') | ||
|
||
PostForm = model_form(BlogPost, base_class=BasePostForm, converter=BlogModelConverter()) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
""" | ||
Admin handlers | ||
""" | ||
|
||
import os, logging, datetime | ||
|
||
from google.appengine.ext import db | ||
from google.appengine.ext import deferred | ||
|
||
from tipfy import (RequestHandler, RequestRedirect, Response, abort, | ||
cached_property, redirect, url_for, render_json_response) | ||
from tipfy.ext.auth import AppEngineAuthMixin, login_required, user_required, admin_required | ||
|
||
from tipfy.ext.jinja2 import Jinja2Mixin, render_response, render_template | ||
from tipfy.ext.session import AllSessionMixins, SessionMiddleware | ||
from tipfy.ext.wtforms import Form, fields, validators | ||
|
||
from ... import config | ||
from ..models import BlogPost | ||
from utils import with_post | ||
from forms import PostForm | ||
from .. import markup | ||
from .. import post_deploy | ||
|
||
class BaseHandler(RequestHandler, AppEngineAuthMixin, Jinja2Mixin): | ||
def render_to_response(self, template_name, template_vals=None, theme=None): | ||
template = os.path.join("admin", template_name) | ||
context = { | ||
'config': config | ||
} | ||
if template_vals: | ||
context.update(template_vals) | ||
|
||
return self.render_response(template, **context) | ||
|
||
|
||
class HomeHandler(BaseHandler): | ||
"""A handler that outputs the result of a rendered template.""" | ||
def get(self, **kwargs): | ||
return render_response('home.html', message='Hello, Jinja!') | ||
|
||
|
||
class AdminHandler(BaseHandler): | ||
@admin_required | ||
def get(self, **kwargs): | ||
""" | ||
Show a list of posts | ||
""" | ||
offset = int(self.request.args.get('start', 0)) | ||
count = int(self.request.args.get('count', 20)) | ||
|
||
posts = BlogPost.all().order('-published').fetch(count, offset) | ||
template_vals = { | ||
'is_admin': True, | ||
'offset': offset, | ||
'count': count, | ||
'last_post': offset + len(posts) - 1, | ||
'prev_offset': max(0, offset - count), | ||
'next_offset': offset + count, | ||
'posts': posts, | ||
} | ||
|
||
return self.render_to_response('index.html', template_vals) | ||
|
||
|
||
|
||
class PostHandler(BaseHandler): | ||
def render_form(self, post=None): | ||
self.form = self.get_form(post) | ||
return self.render_to_response("edit.html", {'form': self.form}) | ||
|
||
@admin_required | ||
@with_post | ||
def get(self, post): | ||
return self.render_form(post) | ||
|
||
@admin_required | ||
@with_post | ||
def post(self, post): | ||
self.form = self.get_form(post) | ||
|
||
newpost = False | ||
if not post: | ||
newpost = True | ||
post = BlogPost(title=self.form.title.data, body=self.form.body.data) | ||
|
||
if self.form.validate(): | ||
self.form.populate_obj(post) | ||
if newpost: | ||
post.published = datetime.datetime.now() | ||
post.updated = datetime.datetime.now() | ||
post.publish() | ||
return self.render_to_response("published.html", {'post': post}) | ||
|
||
return self.render_form() | ||
|
||
def get_form(self, post): | ||
return PostForm(self.request, obj=post) | ||
|
||
class DeleteHandler(BaseHandler): | ||
@with_post | ||
def post(self, post): | ||
if post.path:# Published post | ||
post.remove() | ||
else:# Draft | ||
post.delete() | ||
return self.render_to_response("deleted.html", None) | ||
|
||
class PreviewHandler(RequestHandler): | ||
def get(self): | ||
logging.info('get called') | ||
return Response('test') | ||
|
||
def post(self, **kwargs): | ||
body = self.request.form.get('body') | ||
title = self.request.form.get('title') | ||
body_markup = self.request.form.get('body_markup') | ||
|
||
try: | ||
post = BlogPost(title=title, body=body, body_markup=body_markup) | ||
html = markup.render_body(post) | ||
result = {'success': 'True', | ||
'content': html} | ||
except Exception, e: | ||
error = ("Unable to markup data: %s" % e) | ||
result = {'success': 'False', | ||
'content': error} | ||
return render_json_response(result) | ||
|
||
class RegenerateHandler(BaseHandler): | ||
def post(self): | ||
regen = post_deploy.PostRegenerator() | ||
deferred.defer(regen.regenerate) | ||
deferred.defer(post_deploy.post_deploy, post_deploy.BLOG_VERSION) | ||
return self.render_to_response("regenerating.html") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from ..models import BlogPost | ||
|
||
def with_post(fun, *args, **kwargs): | ||
def decorate(self, post_id=None): | ||
post = None | ||
if post_id: | ||
post = BlogPost.get_by_id(int(post_id)) | ||
if not post: | ||
self.error(404) | ||
return | ||
|
||
return fun(self, post, *args, **kwargs) | ||
return decorate |
Oops, something went wrong.