Skip to content
This repository has been archived by the owner on Sep 3, 2019. It is now read-only.

Commit

Permalink
Added support for authors.
Browse files Browse the repository at this point in the history
  • Loading branch information
myles committed Mar 2, 2011
1 parent e228f47 commit a099c25
Show file tree
Hide file tree
Showing 11 changed files with 171 additions and 11 deletions.
29 changes: 26 additions & 3 deletions blog/feeds.py
Expand Up @@ -67,7 +67,7 @@ def link(self, obj):
return obj.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogCategoryPostFeed"

def items(self, obj):
return obj.post_set.all()
return obj.post_set.published()

def item_link(self, item):
return item.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogCategoryPostFeed"
Expand All @@ -85,7 +85,30 @@ def link(self, obj):
return reverse('blog_tags_detail', args=[obj.name,]) + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogTagPostFeed"

def items(self, obj):
return Post.objects.filter(tags__in=[obj])
return Post.objects.published(tags__in=[obj])

def item_link(self, item):
return item.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogTagPostFeed"
return item.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogTagPostFeed"

class BlogAuthorPostFeed(BaseFeed):
def get_object(self, bits):
if len(bits) != 1:
raise FeedDoesNotExist

return User.objects.filter(username_exact=bits[0])

def title(self, obj):
if obj.get_full_name():
name = obj.get_full_name()
else:
name = obj.username
return u"%s: weblog entries written by %s." % (current_site.name, name)

def link(self, obj):
return reverse('blog_authors_detail', args=[obj.username,]) + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogAuthorPostFeed"

def items(self, obj):
return Post.objects.published(author=obj)

def item_link(self, item):
return item.get_absolute_url() + "?utm_source=feedreader&utm_medium=feed&utm_campaign=BlogAuthorPostFeed"
11 changes: 11 additions & 0 deletions blog/fixtures/auth.json
Expand Up @@ -9,5 +9,16 @@
"last_name": "Braithwaite",
"email": "me@mylesbraithwaite.com"
}
},
{
"pk": 2,
"model": "auth.user",
"fields": {
"username": "batman",
"password": "no-no-no",
"first_name": "Bruce",
"last_name": "Wayne",
"email": "batman@cave.com"
}
}
]
2 changes: 1 addition & 1 deletion blog/fixtures/blog.json
Expand Up @@ -66,7 +66,7 @@
"body": "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque at quam. Vivamus nisl neque, pharetra consequat, tempus sit amet, pretium sit amet, turpis. Nunc non pede. Fusce aliquet. Ut placerat eros quis nunc. Curabitur venenatis placerat velit. Vestibulum erat. Aliquam erat volutpat. Cras id leo a quam euismod placerat. Nunc magna neque, dapibus eu, venenatis ut, pharetra vitae, magna. Aenean erat sem, iaculis sed, eleifend et, porta vitae, arcu. Donec mauris elit, varius vitae, posuere sed, sollicitudin id, elit.\r\n\r\nPellentesque pede. Nunc volutpat cursus quam. Aenean magna justo, congue id, aliquet et, porttitor vitae, risus. Mauris et dui sed tortor congue semper. In placerat tellus ut neque. Phasellus consectetuer dui id purus. Praesent porta convallis urna. Fusce luctus. Vivamus mauris. Etiam pretium. Vivamus tortor nulla, dignissim ac, dapibus quis, ultricies et, nisl. Morbi sit amet est rhoncus quam fringilla rhoncus. Mauris nisl quam, ornare eu, consectetuer eget, mattis nec, lectus. Nulla iaculis leo sed elit. Sed sollicitudin. Phasellus ornare. In hac habitasse platea dictumst.\r\n\r\nLorem ipsum dolor sit amet, consectetuer adipiscing elit. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis ac sem eu neque accumsan euismod. Nam at nulla vitae felis egestas viverra. Praesent nisl. In ut nibh. Etiam a velit. Vivamus tincidunt. Aenean luctus lobortis lectus. Nunc a ante. Sed erat felis, dapibus ut, interdum rutrum, bibendum ut, erat. Maecenas fermentum hendrerit nisl. Donec magna. Pellentesque porttitor facilisis nunc. Nulla iaculis leo. Aenean sem. Maecenas lorem. Etiam vitae urna. Donec quam. Ut non velit in quam dapibus dignissim.\r\n\r\nVivamus dolor nisl, gravida at, pellentesque a, rhoncus ut, nulla. Nullam ullamcorper massa non enim. Aenean vehicula aliquam quam. Donec egestas nisi. Mauris non turpis. Proin quis elit eget nulla interdum fermentum. Sed tristique metus vel eros. Pellentesque hendrerit orci. Donec ornare blandit neque. Morbi viverra varius nibh. Maecenas ultricies magna ac turpis. Sed magna. Phasellus pharetra. Morbi vitae eros. Donec pellentesque, dui ut mattis rutrum, justo turpis iaculis elit, eget molestie leo erat sit amet sapien. Integer condimentum sapien ac ante vestibulum bibendum. Fusce nec erat auctor ipsum ultricies dignissim. Aliquam varius risus a magna. Vivamus libero. Donec quis leo.\r\n\r\nAliquam aliquet, justo in porttitor rutrum, ipsum dolor luctus augue, vel adipiscing risus elit et quam. Maecenas vitae sapien sit amet sem ornare iaculis. Sed lobortis leo. Cras pulvinar erat. Nulla facilisi. Vivamus cursus est ut sapien. Proin in augue eget libero eleifend ornare. Etiam laoreet, dui blandit tempus pulvinar, arcu ligula tempor enim, in eleifend quam urna id est. Donec felis sem, venenatis et, viverra non, tincidunt id, nunc. Curabitur ac mi. Vestibulum ligula augue, aliquam non, ultricies ac, feugiat sit amet, quam. Lorem ipsum dolor sit amet, consectetuer adipiscing elit.",
"allow_comments": true,
"date_added": "2009-01-15 09:17:29",
"author": 1,
"author": 2,
"markup": "linebreaks",
"tease": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.",
"allow_pings": false,
Expand Down
11 changes: 11 additions & 0 deletions blog/sitemaps.py
@@ -1,3 +1,4 @@
from django.contrib.auth.models import User
from django.contrib.sitemaps import Sitemap
from django.core.urlresolvers import reverse

Expand Down Expand Up @@ -39,3 +40,13 @@ def items(self):

def location(self, obj):
return reverse('blog_tags_detail', args=[obj.slug,])

class BlogAuthorSitemap(Sitemap):
changefreq = "monthly"
priority = 0.1

def items(self):
return User.objects.all()

def location(self, obj):
return reverse('blog_authors_detail', args=[obj.username,])
35 changes: 35 additions & 0 deletions blog/templates/blog/author_detail.html
@@ -0,0 +1,35 @@
{% extends "blog/base_blog_archive.html" %}

{% block title %}{{ block.super }}: Blog posts written by {% if author.get_full_name %}{{ author.get_full_name }}{% else %}{{ author }}{% endif %}{% endblock %}

{% block content_title %}
<h2>Blog posts <a href="{% url blog_authors_list %}">written</a> by {% if author.get_full_name %}{{ author.get_full_name }}{% else %}{{ author }}{% endif %}</h2>
{% endblock %}

{% block content %}
<div id="blog_posts">
{% for post in posts.object_list %}{% include "blog/_post.html" %}{% endfor %}
</div>

{% if posts.has_other_pages %}
<ul id="pagination">
{% if posts.has_previous %}
<li class="previous on"><a href="{% url blog_categories_detail_paginated category.slug posts.previous_page_number %}" title="Page {{ posts.previous_page_number }}">Previous</a></li>
{% else %}
<li class="previous off">Previous</li>
{% endif %}
{% for page in posts.page_range %}
{% ifequal page posts.page_number %}
<li class="active">{{ page }}</li>
{% else %}
<li><a href="{% url blog_categories_detail_paginated category.slug page %}">{{ page }}</a></li>
{% endifequal %}
{% endfor %}
{% if posts.has_next %}
<li class="next on"><a href="{% url blog_categories_detail_paginated category.slug posts.next_page_number %}" title="Page {{ posts.next_page_number }}">Next</a></li>
{% else %}
<li class="next off">Next</li>
{% endif %}
</ul>
{% endif %}
{% endblock %}
15 changes: 15 additions & 0 deletions blog/templates/blog/author_list.html
@@ -0,0 +1,15 @@
{% extends "blog/base_blog_archive.html" %}

{% block title %}{{ block.super }}: Blog Authors{% endblock %}

{% block content_title %}
<h2>Blog Authors</h2>
{% endblock %}

{% block content %}
<ul id="blog_authors">
{% for author in authors %}
<li><a href="{% url blog_authors_detail author.username %}">{% if author.get_full_name %}{{ author.get_full_name }}{% else %}{{ author }}{% endif %}</a></li>
{% endfor %}
</ul>
{% endblock %}
16 changes: 14 additions & 2 deletions blog/tests.py
Expand Up @@ -10,7 +10,7 @@ class BlogTestCase(TestCase):

def setUp(self):
self.post = Post.objects.get(pk=1)
self.post.tags.add('Lorem Ipsum')
self.post.tags.add('lorem-ipsum')
self.post.save()
self.category = Category.objects.get(pk=1)
self.client = Client()
Expand Down Expand Up @@ -51,10 +51,18 @@ def testTagList(self):
self.assertEquals(response.status_code, 200)

def testTagDetail(self):
tag = Post.tags.all()[0]
tag = self.post.tags.all()[0]
response = self.client.get(reverse('blog_tags_detail', args=[tag.slug,]))
self.assertEquals(response.status_code, 200)

def testAuthorList(self):
response = self.client.get(reverse('blog_authors_list'))
self.assertEquals(response.status_code, 200)

def testAuthorDetail(self):
response = self.client.get(reverse('blog_authors_detail', args=['myles',]))
self.assertEquals(response.status_code, 200)

def testPostYear(self):
year = self.post.published.year
response = self.client.get(reverse('blog_archive_year', args=[year,]))
Expand Down Expand Up @@ -117,4 +125,8 @@ def testBlogCategoryPostFeed(self):
def testBlogTagPostFeed(self):
response = self.client.get(reverse('blog_tag_post_feed', args=['lorem-ipsum']))
self.assertEquals(response.status_code, 200)

def testBlogAuthorPostFeed(self):
response = self.client.get(reverse('blog_author_post_feed', args=['myles']))
self.assertEquals(response.status_code, 200)

3 changes: 2 additions & 1 deletion blog/testsettings.py
Expand Up @@ -14,7 +14,8 @@

'django_markup',
'taggit',

'django_graffle',

'blog',
]
ROOT_URLCONF = 'blog.testurls'
6 changes: 4 additions & 2 deletions blog/testurls.py
@@ -1,21 +1,23 @@
from django.conf.urls.defaults import patterns, url, include
from django.contrib import admin

from blog.sitemaps import BlogPostSitemap, BlogCategorySitemap, BlogTagSitemap
from blog.feeds import BlogPostFeed, BlogCategoryPostFeed, BlogTagPostFeed
from blog.sitemaps import BlogPostSitemap, BlogCategorySitemap, BlogTagSitemap, BlogAuthorSitemap
from blog.feeds import BlogPostFeed, BlogCategoryPostFeed, BlogTagPostFeed, BlogAuthorPostFeed

admin.autodiscover()

feeds = {
'blog': BlogPostFeed,
'blog-category': BlogCategoryPostFeed,
'blog-tag': BlogTagPostFeed,
'blog-author': BlogAuthorPostFeed
}

sitemaps = {
'blog': BlogPostSitemap,
'blog-category': BlogCategorySitemap,
'blog-tag': BlogTagSitemap,
'blog-author': BlogAuthorSitemap
}

urlpatterns = patterns('',
Expand Down
20 changes: 18 additions & 2 deletions blog/urls.py
@@ -1,6 +1,6 @@
from django.conf.urls.defaults import patterns, url

from blog.feeds import BlogPostFeed, BlogCategoryPostFeed, BlogTagPostFeed
from blog.feeds import BlogPostFeed, BlogCategoryPostFeed, BlogTagPostFeed, BlogAuthorPostFeed

urlpatterns = patterns('',
url(r'feed/$',
Expand All @@ -14,6 +14,10 @@
url(r'category/(?P<slug>[-\w]+)/feed/$',
view = BlogCategoryPostFeed(),
name = 'blog_category_post_feed'
),
url(r'author/(?P<username>[-\w]+)/feed/$',
view = BlogAuthorPostFeed(),
name = 'blog_author_post_feed'
)
)

Expand Down Expand Up @@ -54,10 +58,22 @@
view = 'category_detail',
name = 'blog_categories_detail',
),
url (r'^category/$',
url(r'^category/$',
view = 'category_list',
name = 'blog_categories_list',
),
url(r'^author/(?P<username>[-\w]+)/page/(?P<page>\d+)/$',
view = 'author_detail',
name = 'blog_authors_detail_paginated',
),
url(r'^author/(?P<username>[-\w]+)/$',
view = 'author_detail',
name = 'blog_authors_detail',
),
url(r'^author/$',
view = 'author_list',
name = 'blog_authors_list'
),
url(r'^updated/$',
view = 'updated',
name = 'blog_updated',
Expand Down
34 changes: 34 additions & 0 deletions blog/views.py
Expand Up @@ -2,6 +2,7 @@

from django.http import Http404
from django.template import RequestContext
from django.contrib.auth.models import User
from django.shortcuts import render_to_response
from django.core.paginator import Paginator, InvalidPage, EmptyPage

Expand Down Expand Up @@ -155,6 +156,39 @@ def category_detail(request, slug, page=1, count=5, context={}, template_name='b

return render_to_response(template_name, context, context_instance=RequestContext(request))

def author_list(request, context={}, template_name='blog/author_list.html'):
authors = User.objects.all()

context.update({
'authors': authors,
'is_archive': True
})

return render_to_response(template_name, context, context_instance=RequestContext(request))

def author_detail(request, username, page=1, count=5, context={}, template_name="blog/author_detail.html"):
try:
author = User.objects.get(username__iexact=username)
except User.DoesNotExist:
raise Http404

post_list = Post.objects.published(author=author)

paginator = Paginator(post_list, int(request.GET.get('count', count)))

try:
posts = paginator.page(int(request.GET.get('page', page)))
except (EmptyPage, InvalidPage):
posts = paginator.page(paginator.num_pages)

context.update({
'author': author,
'posts': posts,
'is_archive': True
})

return render_to_response(template_name, context, context_instance=RequestContext(request))

def tag_list(request, context={}, template_name='blog/tag_list.html'):
tags = Post.tags.all()

Expand Down

0 comments on commit a099c25

Please sign in to comment.