Skip to content

Commit

Permalink
This is the first version of Bloggart with support for Pages!
Browse files Browse the repository at this point in the history
* Data are all handled correctly
* Pages support 'parent pages'
* If a Page is set to have a child page as parent page, this is automatically avoided, setting the 'parent_page' field to 'None'
* Pages are listed in the 'Admin' page
* An initial template for pages is created (needs more work)
* Minor CSS touches

What's left to have Pages 100% completed?
1) A template that fully support Pages, and showes Childs and Parent Pages
2) Sitemap.xml needs to generate a map with Pages
3) Sitemap.xml needs to generate a prioritized map based on user preferences
4) Testing :)
5) Adapt the other 2 themes to support pages
  • Loading branch information
detro committed Jan 17, 2011
1 parent 5f3dcfa commit bb870cc
Show file tree
Hide file tree
Showing 11 changed files with 272 additions and 161 deletions.
43 changes: 24 additions & 19 deletions generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import markup
import static
import utils

import models

generator_list = []

Expand Down Expand Up @@ -150,10 +150,13 @@ class PostPrevNextContentGenerator(PostContentGenerator):
"""ContentGenerator for the blog posts chronologically before and after the blog post."""

@classmethod
def get_resource_list(cls, post):
prev, next = cls.get_prev_next(post)
resource_list = [res.key().id() for res in (prev,next) if res is not None]
return resource_list
def get_resource_list(cls, content):
if ( content.kind() == "BlogPost" ):
prev, next = cls.get_prev_next(content);
resource_list = [res.key().id() for res in (prev,next) if res is not None];
return resource_list;
else:
return [];

@classmethod
def generate_resource(cls, post, resource):
Expand Down Expand Up @@ -182,8 +185,11 @@ class ListingContentGenerator(ContentGenerator):
"""The path for the first listing page."""

@classmethod
def get_etag(cls, post):
return post.summary_hash
def get_etag(cls, content):
if ( content.kind() == "BlogPost" ):
return content.summary_hash;
else:
return None;

@classmethod
def _filter_query(cls, resource, q):
Expand Down Expand Up @@ -248,8 +254,9 @@ class TagsContentGenerator(ListingContentGenerator):
first_page_path = '/tag/%(resource)s'

@classmethod
def get_resource_list(cls, post):
return post.normalized_tags
def get_resource_list(cls, content):
# Return normalized tags only if content is of kind 'BlogPost'
return content.normalized_tags if content.kind() == "BlogPost" else [];

@classmethod
def _filter_query(cls, resource, q):
Expand All @@ -267,14 +274,13 @@ class ArchivePageContentGenerator(ListingContentGenerator):
first_page_path = '/archive/%(resource)s/'

@classmethod
def get_resource_list(cls, post):
from models import BlogDate
return [BlogDate.get_key_name(post)]
def get_resource_list(cls, content):
# Return a BlogDate only if content is of kind "BlogPost"
return [models.BlogDate.get_key_name(content)] if content.kind() == "BlogPost" else [];

@classmethod
def _filter_query(cls, resource, q):
from models import BlogDate
ts = BlogDate.datetime_from_key_name(resource)
ts = models.BlogDate.datetime_from_key_name(resource)

# We don't have to bother clearing hour, min, etc., as
# datetime_from_key_name() only sets the year and month.
Expand All @@ -298,18 +304,17 @@ class ArchiveIndexContentGenerator(ContentGenerator):
"""

@classmethod
def get_resource_list(cls, post):
return ["archive"]
def get_resource_list(cls, content):
# Return ['archive'] only if content is of kind "BlogPost"
return ["archive"] if content.kind() == "BlogPost" else [];

@classmethod
def get_etag(cls, post):
return post.hash

@classmethod
def generate_resource(cls, post, resource):
from models import BlogDate

q = BlogDate.all().order('-__key__')
q = models.BlogDate.all().order('-__key__')
dates = [x.date for x in q]
date_struct = {}
for date in dates:
Expand Down
139 changes: 81 additions & 58 deletions handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,35 @@


class PostForm(djangoforms.ModelForm):
title = forms.CharField(widget=forms.TextInput(attrs={'id':'name'}))
body = forms.CharField(widget=forms.Textarea(attrs={
'id':'message',
'rows': 10,
'cols': 20}))
body_markup = forms.ChoiceField(
choices=[(k, v[0]) for k, v in markup.MARKUP_MAP.iteritems()])
tags = forms.CharField(widget=forms.Textarea(attrs={'rows': 5, 'cols': 20}))
draft = forms.BooleanField(required=False)
title = forms.CharField(widget=forms.TextInput( attrs={'id':'name'} ));
body = forms.CharField(widget=forms.Textarea( attrs={'id':'message', 'rows': 10, 'cols': 20} ));
body_markup = forms.ChoiceField( choices=[(k, v[0]) for k, v in markup.MARKUP_MAP.iteritems()] );
tags = forms.CharField(widget=forms.Textarea(attrs={'rows': 5, 'cols': 20}));
draft = forms.BooleanField(required=False);
class Meta:
model = models.BlogPost
fields = [ 'title', 'body', 'tags' ]


class PageForm(djangoforms.ModelForm):
# Overridden constructor to initialise the Form properly
def __init__(self, current_page, *args, **kwargs):
self.base_fields['parent_page'].query = models.Page.all();
if ( current_page ):
# Show all the pages, except the one associated with the current form instance
self.base_fields['parent_page'].query.filter("__key__ != ", current_page.key());

self.base_fields['parent_page'].widget.choices = self.base_fields['parent_page'].choices;
super(PageForm, self).__init__(*args, **kwargs);

title = forms.CharField( widget=forms.TextInput( attrs={'id':'name'} ));
parent_page = djangoforms.ModelChoiceField( models.Page, None, required=False, initial=None, empty_label="none" );
body = forms.CharField( widget=forms.Textarea( attrs={'id':'message', 'rows': 10, 'cols': 20} ));
body_markup = forms.ChoiceField( choices=[(k, v[0]) for k, v in markup.MARKUP_MAP.iteritems()] );
draft = forms.BooleanField( required=False );
class Meta:
model = models.Page
fields = [ 'title', 'parent_page', 'body' ]


def with_post(fun):
Expand Down Expand Up @@ -71,24 +88,33 @@ def render_to_response(self, template_name, template_vals=None, theme=None):
class AdminHandler(BaseHandler):
def get(self):
from generators import generator_list
offset = int(self.request.get('start', 0))
count = int(self.request.get('count', 20))
posts = models.BlogPost.all().order('-published').fetch(count, offset)
posts_offset = int(self.request.get('posts_start', 0));
posts_count = int(self.request.get('posts_count', 20));
posts = models.BlogPost.all().order('-published').fetch(posts_count, posts_offset);
pages_offset = int(self.request.get('pages_start', 0));
pages_count = int(self.request.get('pages_count', 20));
pages = models.Page.all().order('-published').fetch(pages_count, pages_offset);
template_vals = {
'offset': offset,
'count': count,
'last_post': offset + len(posts) - 1,
'prev_offset': max(0, offset - count),
'next_offset': offset + count,
'posts_offset': posts_offset,
'posts_count': posts_count,
'posts_last_post': posts_offset + len(posts) - 1,
'posts_prev_offset': max(0, posts_offset - posts_count),
'posts_next_offset': posts_offset + posts_count,
'posts': posts,
'pages_offset': pages_offset,
'pages_count': pages_count,
'pages_last_page': pages_offset + len(pages) - 1,
'pages_prev_offset': max(0, pages_offset - pages_count),
'pages_next_offset': pages_offset + pages_count,
'pages': pages,
'generators': [cls.__name__ for cls in generator_list],
}
self.render_to_response("index.html", template_vals)
};
self.render_to_response("index.html", template_vals);


class PostHandler(BaseHandler):
def render_form(self, form):
self.render_to_response("edit.html", {'form': form})
self.render_to_response("edit_post.html", {'form': form})

@with_post
def get(self, post):
Expand All @@ -105,17 +131,18 @@ def post(self, post):
initial={'draft': post and post.published is None})
if form.is_valid():
post = form.save(commit=False)
if form.clean_data['draft']:# Draft post
if form.clean_data['draft']: # Draft post
post.published = datetime.datetime.max
post.put()
else:
if not post.path: # Publish post
post.updated = post.published = datetime.datetime.now(utils.tzinfo())
else:# Edit post
else: # Edit post
post.updated = datetime.datetime.now(utils.tzinfo())
post.publish()
self.render_to_response("published.html", {
'post': post,
'content': post,
'type' : 'post',
'draft': form.clean_data['draft']})
else:
self.render_form(form)
Expand All @@ -128,7 +155,7 @@ def post(self, post):
post.remove();
else: # Draft
post.delete();
self.render_to_response("deleted.html", None);
self.render_to_response("deleted.html", {'type' : 'post'});


class PreviewPostHandler(BaseHandler):
Expand All @@ -139,57 +166,56 @@ def get(self, post):
# datetime.max and a "real" date looks better.
if post.published == datetime.datetime.max:
post.published = datetime.datetime.now(utils.tzinfo());
self.response.out.write(utils.render_template('post.html', {
'post': post,
'is_admin': True
}));
self.response.out.write(utils.render_template('post.html', {'post' : post, 'is_admin' : True}));


class PageHandler(BaseHandler):
def render_form(self, form):
self.render_to_response("edit.html", {'form': form})
self.render_to_response("edit_page.html", {'form': form})

@with_page
def get(self, page):
# TODO
self.render_form(PostForm(
instance=post,
initial={
'draft': post and not post.path,
'body_markup': post and post.body_markup or config.default_markup,
}))
self.render_form(PageForm(instance=page,
current_page=page,
initial={
'draft': page and not page.path,
'body_markup': page and page.body_markup or config.default_markup
}));

@with_page
def post(self, page):
# TODO
form = PostForm(data=self.request.POST, instance=post,
initial={'draft': post and post.published is None})
form = PageForm(current_page=page, data=self.request.POST, instance=page, initial={'draft': page and page.published is None});
if form.is_valid():
post = form.save(commit=False)
if form.clean_data['draft']:# Draft post
post.published = datetime.datetime.max
post.put()
page = form.save(commit=False);

# Ensure that a 'Child Page' is never asigned as 'Parent Page' as well
for p in page.child_pages:
if ( page.parent_page.key() == p.key() ):
page.parent_page = None;
page.put();
break;

if form.clean_data['draft']: # Draft page
page.published = datetime.datetime.max;
page.put();
else:
if not post.path: # Publish post
post.updated = post.published = datetime.datetime.now(utils.tzinfo())
else:# Edit post
post.updated = datetime.datetime.now(utils.tzinfo())
post.publish()
self.render_to_response("published.html", {
'post': post,
'draft': form.clean_data['draft']})
if not page.path: # Publish post
page.updated = page.published = datetime.datetime.now(utils.tzinfo());
else: # Edit post
page.updated = datetime.datetime.now(utils.tzinfo());
page.publish();
self.render_to_response("published.html", {'content': page, 'type' : 'page', 'draft': form.clean_data['draft']});
else:
self.render_form(form)
self.render_form(form);

class DeletePageHandler(BaseHandler):
@with_page
def post(self, page):
# TODO
if page.path: # Published post
page.remove();
else: # Draft
page.delete();
self.render_to_response("deleted.html", None);
self.render_to_response("deleted.html", {'type' : 'page'});


class PreviewPageHandler(BaseHandler):
Expand All @@ -200,10 +226,7 @@ def get(self, page):
# datetime.max and a "real" date looks better.
if page.published == datetime.datetime.max:
page.published = datetime.datetime.now(utils.tzinfo());
self.response.out.write(utils.render_template('page.html', {
'page': page,
'is_admin': True
}));
self.response.out.write(utils.render_template('page.html', {'page' : page, 'is_admin' : True}));


class RegenerateHandler(BaseHandler):
Expand Down
8 changes: 8 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ def date(self):


class Page(db.Model):
# Overridden to show a "human readable" name when used in Django Forms.
# It adds a "prefix" with the name of the "Parent Page", if any.
def __unicode__(self):
parent_prefix = "";
if ( self.parent_page != None ):
parent_prefix = self.parent_page.title + u" \u00BB ";
return parent_prefix + self.title;

# The URL path to the page. Pages have a path iff they are published.
path = db.StringProperty();
title = db.StringProperty(required=True, indexed=False);
Expand Down
2 changes: 1 addition & 1 deletion themes/squared/admin/deleted.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
{% block body %}
<div id="main">
<h1>Deleted!</h1>
<p>Your post has been removed.</p>
<p>Your {{ type }} has been removed.</p>
</div>
{% endblock %}
60 changes: 0 additions & 60 deletions themes/squared/admin/edit.html

This file was deleted.

Loading

0 comments on commit bb870cc

Please sign in to comment.