Add a news app, and enable commenting
This commit is contained in:
0
news/__init__.py
Normal file
0
news/__init__.py
Normal file
4
news/admin.py
Normal file
4
news/admin.py
Normal file
@@ -0,0 +1,4 @@
|
||||
import models
|
||||
from django.contrib import admin
|
||||
|
||||
admin.site.register(models.Post)
|
48
news/models.py
Normal file
48
news/models.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
def unique_slug(item,slug_source,slug_field):
|
||||
"""Ensures a unique slug field by appending an integer counter to duplicate slugs.
|
||||
|
||||
The item's slug field is first prepopulated by slugify-ing the source field. If that value already exists, a counter is appended to the slug, and the counter incremented upward until the value is unique.
|
||||
|
||||
For instance, if you save an object titled Daily Roundup, and the slug daily-roundup is already taken, this function will try daily-roundup-2, daily-roundup-3, daily-roundup-4, etc, until a unique value is found.
|
||||
|
||||
Call from within a model's custom save() method like so:
|
||||
unique_slug(item, slug_source='field1', slug_field='field2')
|
||||
where the value of field slug_source will be used to prepopulate the value of slug_field.
|
||||
"""
|
||||
if not getattr(item, slug_field): # if it's already got a slug, do nothing.
|
||||
from django.template.defaultfilters import slugify
|
||||
slug = slugify(getattr(item,slug_source))
|
||||
itemModel = item.__class__
|
||||
# the following gets all existing slug values
|
||||
allSlugs = [sl.values()[0] for sl in itemModel.objects.values(slug_field)]
|
||||
if slug in allSlugs:
|
||||
import re
|
||||
counterFinder = re.compile(r'-\d+$')
|
||||
counter = 2
|
||||
slug = "%s-%i" % (slug, counter)
|
||||
while slug in allSlugs:
|
||||
slug = re.sub(counterFinder,"-%i" % counter, slug)
|
||||
counter += 1
|
||||
setattr(item,slug_field,slug)
|
||||
|
||||
class Post(models.Model):
|
||||
title = models.CharField(max_length=100)
|
||||
body = models.TextField()
|
||||
slug = models.SlugField(blank=True)
|
||||
author = models.ForeignKey(User, related_name='news_posts')
|
||||
created = models.DateTimeField(editable=False, auto_now_add=True)
|
||||
updated = models.DateTimeField(editable=False, auto_now=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.title
|
||||
|
||||
@models.permalink
|
||||
def get_absolute_url(self):
|
||||
return ('news.views.view', [], {'slug':self.slug})
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
unique_slug(self, slug_source='title', slug_field='slug')
|
||||
super(Post, self).save(*args, **kwargs)
|
16
news/tests.py
Normal file
16
news/tests.py
Normal file
@@ -0,0 +1,16 @@
|
||||
"""
|
||||
This file demonstrates writing tests using the unittest module. These will pass
|
||||
when you run "manage.py test".
|
||||
|
||||
Replace this with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.assertEqual(1 + 1, 2)
|
7
news/urls.py
Normal file
7
news/urls.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from django.conf.urls.defaults import patterns, include, url
|
||||
|
||||
urlpatterns = patterns('news',
|
||||
url('^$', 'views.index'),
|
||||
url('^(?P<page>[0-9]+)$', 'views.index'),
|
||||
url('^(?P<slug>.*)$', 'views.view')
|
||||
)
|
17
news/views.py
Normal file
17
news/views.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import models
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
|
||||
def index(request, page=0):
|
||||
all_news = models.Post.objects.all()
|
||||
paginator = Paginator(all_news, 25)
|
||||
try:
|
||||
items = paginator.page(page)
|
||||
except EmptyPage:
|
||||
items = paginator.page(paginator.num_pages)
|
||||
return render_to_response('news/index.html', {'items':items}, context_instance = RequestContext(request))
|
||||
|
||||
def view(request, slug):
|
||||
item = models.Post.objects.get(slug__exact=slug)
|
||||
return render_to_response('news/view.html', {'item':item}, context_instance = RequestContext(request))
|
16
templates/news/index.html
Normal file
16
templates/news/index.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load markup %}
|
||||
{% load comments %}
|
||||
|
||||
{% block title %}News{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% for post in items.object_list %}
|
||||
<h2><a href="{{post.get_absolute_url}}">{{post.title}}</a></h2>
|
||||
<div class="byline">By {{post.author}}</div>
|
||||
<div class="content">
|
||||
{{post.body|markdown}}
|
||||
</div>
|
||||
<div class="commentcount">{% get_comment_count for post as comment_count %}{{comment_count}} comments.</div>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
34
templates/news/view.html
Normal file
34
templates/news/view.html
Normal file
@@ -0,0 +1,34 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load markup %}
|
||||
{% load comments %}
|
||||
{% block title %}News - {{item.title}}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h2><a href="{{post.get_absolute_url}}">{{post.title}}</a></h2>
|
||||
<div class="byline">By {{item.author}}</div>
|
||||
<div class="content">
|
||||
{{item.body|markdown}}
|
||||
</div>
|
||||
<div class="commentcount">{% get_comment_count for item as comment_count %}{{comment_count}} comments.</div>
|
||||
<div class="comments">
|
||||
{% if comment_count > 0 %}
|
||||
<h3>Comments</h3>
|
||||
{% get_comment_list for item as comment_list %}
|
||||
{% for comment in comment_list %}
|
||||
<a name="c{{ comment.id }}" href="{% get_comment_permalink comment %}">#{{comment.id}}</a> by {{comment.user}}
|
||||
<div class="comment">
|
||||
{{comment.comment|markdown:"safe"}}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% get_comment_form for item as form %}
|
||||
<h4>Add a comment</h4>
|
||||
<form action="{% comment_form_target %}" method="post">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" name="submit" value="Post">
|
||||
<input type="submit" name="preview" value="Preview">
|
||||
<input type="hidden" name="next" value="{{post.get_absolute_url}}" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
2
urls.py
2
urls.py
@@ -6,6 +6,8 @@ admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns('',
|
||||
url(r'^$', 'forums.views.index', name='home'),
|
||||
url(r'^comments/', include('django.contrib.comments.urls')),
|
||||
url(r'^news/', include('news.urls')),
|
||||
url(r'^profiles/', include('profiles.urls')),
|
||||
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
|
Reference in New Issue
Block a user