-
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.
Initial commit of stipped down code and templates
- Loading branch information
Showing
31 changed files
with
1,031 additions
and
3 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
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 @@ | ||
[ | ||
{ | ||
"pk": 1, | ||
"model": "sites.site", | ||
"fields": { | ||
"domain": "http://localhost:8000", | ||
"name": "Leaves" | ||
} | ||
}, | ||
{ | ||
"pk": 1, | ||
"model": "leaves.preferences", | ||
"fields": { | ||
"default_comment_status": "pending", | ||
"stream_count": 10, | ||
"analytics_id": "", | ||
"site": 1, | ||
"feed_count": 10, | ||
"homepage": "blog-index" | ||
} | ||
} | ||
] |
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,104 @@ | ||
from django.utils.translation import ugettext_lazy as _ | ||
from django.contrib import admin | ||
from django.contrib.sites.models import Site | ||
from leaves.models import Tag, Comment, Attachment, Redirect, Preferences, Page | ||
|
||
PUBLISHING_OPTIONS = (_('Publishing Options'), { | ||
'fields': ('author', 'author_name', 'status', 'date_published', 'date_expires', 'tags'), | ||
}) | ||
|
||
ADVANCED_PUBLISHING_OPTIONS = (_('Advanced Publishing Options'), { | ||
'classes': ('collapse',), | ||
'fields': ('sites', 'show_in_stream', 'allow_comments', 'password', 'custom_url', 'summary_template', | ||
'page_template'), | ||
}) | ||
|
||
SITEMAP_OPTIONS = (_('Sitemap Options'), { | ||
'classes': ('collapse',), | ||
'fields': ('changefreq', 'priority'), | ||
}) | ||
|
||
TRANSLATION_OPTIONS = (_('Translation Options'), { | ||
'classes': ('collapse',), | ||
'fields': ('language', 'translation_of', 'translator_name'), | ||
}) | ||
|
||
class AttachmentInline (admin.TabularInline): | ||
model = Attachment | ||
extra = 1 | ||
|
||
class LeafAdmin (admin.ModelAdmin): | ||
list_display = ('__unicode__', 'language', 'author_name', 'status', 'date_published', 'date_expires', | ||
'date_created', 'date_modified', 'show_in_stream', 'url') | ||
list_filter = ('author', 'sites', 'status', 'show_in_stream', 'language') | ||
list_select_related = True | ||
date_hierarchy = 'date_published' | ||
inlines = (AttachmentInline,) | ||
|
||
def url(self, obj): | ||
if obj.custom_url: | ||
return obj.custom_url | ||
elif hasattr(obj, 'get_absolute_url'): | ||
return obj.get_absolute_url() | ||
return '' | ||
url.short_description = 'URL' | ||
|
||
def formfield_for_dbfield(self, db_field, **kwargs): | ||
if db_field.name == 'author_name' and 'request' in kwargs: | ||
kwargs['initial'] = kwargs['request'].user.get_full_name().strip() | ||
return super(LeafAdmin, self).formfield_for_dbfield(db_field, **kwargs) | ||
|
||
def formfield_for_foreignkey(self, db_field, request, **kwargs): | ||
if db_field.name == 'author': | ||
if not request.user.is_superuser: | ||
kwargs['queryset'] = User.objects.filter(pk=request.user.pk) | ||
kwargs['initial'] = request.user.pk | ||
return super(LeafAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs) | ||
|
||
def formfield_for_manytomany(self, db_field, request, **kwargs): | ||
if db_field.name == 'sites': | ||
kwargs['initial'] = Site.objects.all() | ||
return super(LeafAdmin, self).formfield_for_manytomany(db_field, request, **kwargs) | ||
|
||
class CommentAdmin (admin.ModelAdmin): | ||
list_display = ('leaf', 'title', 'author_name', 'email', 'status', 'date_posted') | ||
list_filter = ('date_posted', 'status', 'leaf__sites') | ||
date_hierarchy = 'date_posted' | ||
search_fields = ('title', 'comment', 'author_name', 'email') | ||
actions = ('approve_comments',) | ||
ordering = ('-date_posted',) | ||
|
||
def approve_comments(self, request, queryset): | ||
update_count = queryset.update(status='published') | ||
term = 'comment was' if update_count == 1 else 'comments were' | ||
self.message_user(request, '%s %s successfully approved.' % (update_count, term)) | ||
approve_comments.short_description = 'Mark selected comments as published' | ||
|
||
class TagAdmin (admin.ModelAdmin): | ||
list_display = ('name', 'slug') | ||
prepopulated_fields = {'slug': ('name',)} | ||
|
||
class RedirectAdmin (admin.ModelAdmin): | ||
list_display = ('old_path', 'new_path', 'site', 'redirect_type') | ||
list_filter = ('site', 'redirect_type') | ||
|
||
class PreferencesAdmin (admin.ModelAdmin): | ||
list_display = ('site', 'homepage', 'stream_count', 'feed_count', 'analytics_id', 'default_comment_status') | ||
|
||
class PageAdmin (LeafAdmin): | ||
fieldsets = ( | ||
(None, { | ||
'fields': ('title', 'slug', 'summary', 'content'), | ||
}), | ||
PUBLISHING_OPTIONS, | ||
ADVANCED_PUBLISHING_OPTIONS, | ||
SITEMAP_OPTIONS, | ||
TRANSLATION_OPTIONS, | ||
) | ||
prepopulated_fields = {'slug': ('title',)} | ||
|
||
admin.site.register(Tag, TagAdmin) | ||
admin.site.register(Comment, CommentAdmin) | ||
admin.site.register(Redirect, RedirectAdmin) | ||
admin.site.register(Preferences, PreferencesAdmin) | ||
admin.site.register(Page, PageAdmin) |
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,19 @@ | ||
from django.utils.translation import ugettext_lazy as _ | ||
from django.contrib import admin | ||
from leaves.admin import LeafAdmin, PUBLISHING_OPTIONS, ADVANCED_PUBLISHING_OPTIONS, SITEMAP_OPTIONS, \ | ||
TRANSLATION_OPTIONS | ||
from leaves.blog.models import Post | ||
|
||
class PostAdmin (LeafAdmin): | ||
fieldsets = ( | ||
(None, { | ||
'fields': ('title', 'slug', 'summary', 'content'), | ||
}), | ||
PUBLISHING_OPTIONS, | ||
ADVANCED_PUBLISHING_OPTIONS, | ||
SITEMAP_OPTIONS, | ||
TRANSLATION_OPTIONS, | ||
) | ||
prepopulated_fields = {'slug': ('title',)} | ||
|
||
admin.site.register(Post, PostAdmin) |
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 @@ | ||
from django.db import models | ||
from django.utils.translation import ugettext_lazy as _ | ||
from leaves.models import Leaf | ||
from leaves.managers import LeafManager | ||
|
||
class Post (Leaf): | ||
title = models.CharField(_('title'), max_length=200) | ||
slug = models.SlugField(_('slug'), unique=True) | ||
summary = models.TextField(_('summary'), blank=True) | ||
content = models.TextField(_('content')) | ||
|
||
objects = LeafManager() | ||
|
||
def __unicode__(self): | ||
return self.title | ||
__unicode__.admin_order_field = 'title' | ||
|
||
def natural_key(self): | ||
return (self.slug,) | ||
|
||
@models.permalink | ||
def get_absolute_url(self): | ||
return ('blog-post', (), { | ||
'year': str(self.date_published.year), | ||
'month': '%02d' % self.date_published.month, | ||
'slug': self.slug, | ||
}) |
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,9 @@ | ||
from django.conf.urls import patterns, include, url | ||
from leaves.utils import homepage | ||
|
||
urlpatterns = patterns('', | ||
url(r'^$', 'leaves.blog.views.index', name='blog-index'), | ||
url(r'^(?P<year>\d+)/(?P<month>\d+)/(?P<slug>[^/]+)/$', 'leaves.blog.views.post', name='blog-post'), | ||
) | ||
|
||
homepage.register('blog-index', 'Recent Blog Posts') |
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,16 @@ | ||
from django.shortcuts import render, get_object_or_404 | ||
from leaves.blog.models import Post | ||
from leaves.utils import get_page | ||
|
||
def index(request): | ||
qs = Post.objects.stream(site=request.site, user=request.user) | ||
return render(request, 'blog/index.html', { | ||
'page': get_page(request, qs, request.site.preferences.stream_count), | ||
}) | ||
|
||
def post(request, year, month, slug): | ||
qs = Post.objects.stream(site=request.site, user=request.user) | ||
post = get_object_or_404(qs, date_published__year=year, date_published__month=month, slug__iexact=slug) | ||
return render(request, post.get_page_templates(), { | ||
'post': post, | ||
}) |
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,46 @@ | ||
from django.db import models | ||
from django.utils import timezone | ||
|
||
class NaturalKeyManager (models.Manager): | ||
""" | ||
""" | ||
|
||
def __init__(self, *field_names): | ||
self.field_names = tuple(field_names) or ('slug',) | ||
super(NaturalKeyManager, self).__init__() | ||
|
||
def get_by_natural_key(self, *keys): | ||
if len(self.field_names) != len(keys): | ||
raise ValueError('Could not get %s by natural key: %s' % (self.model.__class__, keys)) | ||
params = dict(zip(self.field_names, keys)) | ||
return self.get(**params) | ||
|
||
class LeafManager (NaturalKeyManager): | ||
""" | ||
""" | ||
|
||
def get_query_set(self): | ||
qs = super(LeafManager, self).get_query_set() | ||
# Get all the non-null ForeignKey fields. | ||
related = [f.name for f in self.model._meta.fields if isinstance(f, models.ForeignKey) and not f.null] | ||
if self.model.__name__ == 'Leaf': | ||
# Now get all the subclasses of Leaf to select the reverse relation of the OneToOneFields. | ||
related += [cls.__name__.lower() for cls in self.model.__subclasses__()] | ||
return qs.select_related(*related) | ||
|
||
def published(self, site=None, user=None, asof=None): | ||
if asof is None: | ||
asof = timezone.now() | ||
exp = models.Q(date_expires__isnull=True) | models.Q(date_expires__gt=asof) | ||
q = models.Q(status='published') & models.Q(date_published__lte=asof) & exp | ||
if site: | ||
q &= models.Q(sites__in=(site,)) | ||
# Show the user's leaves in the published stream, even if they aren't. This is particularly useful for the | ||
# admin's "Show on site" feature. | ||
if user and user.is_authenticated(): | ||
q |= models.Q(author=user) | ||
return self.get_query_set().filter(q) | ||
|
||
def stream(self, site=None, user=None, asof=None): | ||
qs = self.published(site=site, user=user, asof=asof) | ||
return qs.filter(show_in_stream=True) |
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,83 @@ | ||
from django.shortcuts import get_object_or_404 | ||
from django.core.urlresolvers import resolve | ||
from django.contrib.sites.models import Site | ||
from django.utils.encoding import iri_to_uri | ||
from django.conf import settings | ||
from django import http | ||
from leaves.models import Leaf, Redirect | ||
import threading | ||
|
||
request_context = threading.local() | ||
|
||
class LeavesSiteMiddleware (object): | ||
|
||
def process_request(self, request): | ||
host = request.get_host().lower().split(':')[0] | ||
# In order to support subdomains, we need to check all the sites | ||
# to find the most specific. | ||
all_sites = {} | ||
default_site = None | ||
for s in Site.objects.select_related('preferences'): | ||
all_sites[s.domain.lower()] = s | ||
if s.pk == settings.SITE_ID: | ||
default_site = s | ||
# If all else fails, fall back to using SITE_ID. | ||
request.site = default_site | ||
if host in all_sites: | ||
request.site = all_sites[host] | ||
else: | ||
# Find the most specific match, determined by match suffix length. | ||
best_match = None | ||
match_len = 0 | ||
for domain, site in all_sites.items(): | ||
if host.endswith(domain) and len(domain) > match_len: | ||
best_match = site | ||
match_len = len(domain) | ||
if best_match: | ||
request.site = best_match | ||
request_context.site = request.site | ||
|
||
def process_response(self, request, response): | ||
if hasattr(request_context, 'site'): | ||
del request_context.site | ||
return response | ||
|
||
class LeavesFallbackMiddleware (object): | ||
|
||
def process_response(self, request, response): | ||
if response.status_code != 404: | ||
return response | ||
try: | ||
url = request.path_info | ||
if not url.endswith('/') and settings.APPEND_SLASH: | ||
return http.HttpResponseRedirect('%s/' % request.path) | ||
if not url.startswith('/'): | ||
url = '/' + url | ||
leaf = get_object_or_404(Leaf, custom_url=url) | ||
leaf = leaf.resolve() | ||
# We need to try to find the view that normally renders this Leaf | ||
# type. Since the URL is custom, we fall back to trying | ||
# get_absolute_url on the Leaf subclass, which should return a URL | ||
# mapped in the plugin's urlconf. | ||
match = resolve(leaf.get_absolute_url()) | ||
r = match.func(request, *match.args, **match.kwargs) | ||
# If the response is a TemplateResponse, we need to bake it. | ||
if hasattr(r, 'render'): | ||
r.render() | ||
return r | ||
except http.Http404: | ||
# If we still haven't found anything, check the redirects. | ||
try: | ||
url = request.get_full_path() | ||
r = Redirect.objects.get(old_path=url, site=request.site) | ||
if not r.new_path: | ||
return http.HttpResponseGone() | ||
resp = http.HttpResponse(status=r.redirect_type) | ||
resp['Location'] = iri_to_uri(r.new_path) | ||
return resp | ||
except Redirect.DoesNotExist: | ||
return response | ||
except: | ||
if settings.DEBUG: | ||
raise | ||
return response |
Oops, something went wrong.