MrOxiMoron / cmsplugin-news
A news application which is pluggable into django-cms. Just so you know, I've been kinda busy with other programming tasks which didn't involve django cms. This I don't know if this still work with the latest version or not.
$ hg clone http://bitbucket.org/MrOxiMoron/cmsplugin-news/
| commit 1: | 896848a60433 |
| parent 0: | c20998e43350 |
| branch: | default |
Changed (Δ7.6 KB):
README.txt (41 lines added, 3 lines removed)
__init__.py
admin.py
cmsplugin_news/__init__.py (null-size change)
cmsplugin_news/admin.py (16 lines added, 0 lines removed)
cmsplugin_news/models.py (48 lines added, 0 lines removed)
cmsplugin_news/navigation.py (56 lines added, 0 lines removed)
cmsplugin_news/templates/cmsplugin_news/news_archive.html (5 lines added, 0 lines removed)
cmsplugin_news/templates/cmsplugin_news/news_archive_day.html (9 lines added, 0 lines removed)
cmsplugin_news/templates/cmsplugin_news/news_archive_month.html (9 lines added, 0 lines removed)
cmsplugin_news/templates/cmsplugin_news/news_archive_year.html (7 lines added, 0 lines removed)
cmsplugin_news/templates/cmsplugin_news/news_detail.html (6 lines added, 0 lines removed)
cmsplugin_news/tests.py (23 lines added, 0 lines removed)
cmsplugin_news/urls.py (32 lines added, 0 lines removed)
cmsplugin_news/views.py (1 lines added, 0 lines removed)
models.py
navigation.py
templates/news/news_archive.html
templates/news/news_archive_day.html
templates/news/news_archive_month.html
templates/news/news_archive_year.html
templates/news/news_detail.html
tests.py
urls.py
views.py
1 |
CMS integration: |
|
1 |
ALPHA |
|
2 |
||
3 |
Name: cmsplugin-news |
|
4 |
Description: A news plugin for django-cms |
|
5 |
Download: http://bitbucket.org/MrOxiMoron/cmsplugin-news/ |
|
6 |
||
7 |
Requirements: |
|
8 |
- django-cms-2.0: rev 2b59edde3cf1c140edfb14b544f2fbcbd56073f8 |
|
9 |
- django: 1.1.1 |
|
10 |
||
11 |
Last tested with: |
|
12 |
- django-cms-2.0: rev 2b59edde3cf1c140edfb14b544f2fbcbd56073f8 |
|
13 |
- django: 1.1.1 |
|
14 |
||
15 |
Setup |
|
16 |
- make sure requirements are installed and properly working |
|
17 |
- add cmsplugin_news to python path |
|
18 |
- add 'cmsplugin_news' to INSTALLED_APPS |
|
19 |
- run 'python manage.py syncdb' |
|
20 |
- Add the cmsplugin_news.urls to the CMS_APPLICATIONS_URLS setting |
|
21 |
- Add the cmsplugin_news.navigation.get_nodes to the CMS_NAVIGATION_EXTENDERS setting |
|
22 |
- Create a page and link the application and navigation to it. |
|
23 |
- Create the propper templates for your site, the ones included with the app are VERY basic |
|
24 |
||
25 |
Todo and Tomaybes: |
|
26 |
- Add tests |
|
27 |
- Allow comments on news (add option to the news model for it) |
|
28 |
- Add migrations |
|
29 |
- Optimize the navigation code, it works but there is probably a better way to do it. |
|
30 |
- Add RSS feed |
|
31 |
- Use the textplugin's way of using a editor for the content |
|
32 |
- Add excerpt |
|
33 |
- Add optional author field |
|
34 |
- Add optional end date to hide news again |
|
35 |
- Add Tags |
|
36 |
- Add translations (I can do the dutch one) |
|
37 |
- Ideas other people come up with :D |
|
38 |
||
39 |
Examples: |
|
2 |
40 |
|
3 |
41 |
CMS_APPLICATIONS_URLS = ( |
4 |
(' |
|
42 |
('cmsplugin_news.urls', 'News'), |
|
5 |
43 |
) |
6 |
44 |
CMS_NAVIGATION_EXTENDERS = ( |
7 |
(' |
|
45 |
('cmsplugin_news.navigation.get_nodes','News navigation'), |
|
8 |
46 |
) |
Up to file-list cmsplugin_news/admin.py:
1 |
from django.contrib import admin |
|
2 |
||
3 |
from cmsplugin_news.models import News |
|
4 |
||
5 |
class NewsAdmin(admin.ModelAdmin): |
|
6 |
date_hierarchy = 'pub_date' |
|
7 |
list_display = ('slug', 'title', 'is_published') |
|
8 |
list_editable = ('title', 'is_published') |
|
9 |
list_filter = ('is_published', ) |
|
10 |
search_fields = ['title', 'content'] |
|
11 |
prepopulated_fields = {'slug': ('title',)} |
|
12 |
||
13 |
save_as = True |
|
14 |
save_on_top = True |
|
15 |
||
16 |
admin.site.register(News, NewsAdmin) |
Up to file-list cmsplugin_news/models.py:
1 |
import datetime |
|
2 |
||
3 |
from django.db import models |
|
4 |
from django.utils.translation import ugettext_lazy as _ |
|
5 |
||
6 |
class PublishedNewsManager(models.Manager): |
|
7 |
""" |
|
8 |
Filters out all unpublished and items with a publication date in the future |
|
9 |
""" |
|
10 |
def get_query_set(self): |
|
11 |
return super(PublishedNewsManager, self).get_query_set() \ |
|
12 |
.filter(is_published=True) \ |
|
13 |
.filter(pub_date__lte=datetime.datetime.now()) |
|
14 |
||
15 |
class News(models.Model): |
|
16 |
""" |
|
17 |
News |
|
18 |
""" |
|
19 |
||
20 |
title = models.CharField(_('Title'), max_length=255) |
|
21 |
slug = models.SlugField(_('Slug'), unique_for_date='pub_date', |
|
22 |
help_text=_('A slug is a short name which uniquely identifies the news item for this day')) |
|
23 |
content = models.TextField(_('Content'), blank=True) |
|
24 |
||
25 |
is_published = models.BooleanField(_('Published'), default=False) |
|
26 |
pub_date = models.DateTimeField(_('Publication date'), default=datetime.datetime.now()) |
|
27 |
||
28 |
created = models.DateTimeField(auto_now_add=True, editable=False) |
|
29 |
updated = models.DateTimeField(auto_now=True, editable=False) |
|
30 |
||
31 |
published = PublishedNewsManager() |
|
32 |
objects = models.Manager() |
|
33 |
||
34 |
class Meta: |
|
35 |
verbose_name = _('News') |
|
36 |
verbose_name_plural = _('News') |
|
37 |
ordering = ('-pub_date', ) |
|
38 |
||
39 |
def __unicode__(self): |
|
40 |
return self.title |
|
41 |
||
42 |
@models.permalink |
|
43 |
def get_absolute_url(self): |
|
44 |
return ('news_detail', (), { 'year': self.pub_date.strftime("%Y"), |
|
45 |
'month': self.pub_date.strftime("%m"), |
|
46 |
'day': self.pub_date.strftime("%d"), |
|
47 |
'slug': self.slug }) |
|
48 |
1 |
from datetime import datetime |
|
2 |
from django.core.urlresolvers import reverse |
|
3 |
||
4 |
from cms.utils.navigation import NavigationNode |
|
5 |
||
6 |
from cmsplugin_news.models import News |
|
7 |
||
8 |
def get_nodes(request): |
|
9 |
res = [] |
|
10 |
||
11 |
items = News.published.all() |
|
12 |
||
13 |
years_done = [] |
|
14 |
months_done = [] |
|
15 |
days_done = [] |
|
16 |
slug_done = [] |
|
17 |
||
18 |
for item in items: |
|
19 |
date = item.pub_date |
|
20 |
||
21 |
if not date.year in years_done: |
|
22 |
years_done.append(date.year) |
|
23 |
year_node = NavigationNode(date.year, reverse('news_archive_year', kwargs=dict(year=date.year))) |
|
24 |
year_node.childrens = [] |
|
25 |
months_done = [] |
|
26 |
res.append(year_node) |
|
27 |
||
28 |
if not date.month in months_done: |
|
29 |
months_done.append(date.month) |
|
30 |
month_node = NavigationNode(datetime.strftime(date, '%B'), |
|
31 |
reverse('news_archive_month', kwargs=dict( |
|
32 |
year=date.year, |
|
33 |
month=datetime.strftime(date, '%m')))) |
|
34 |
month_node.childrens = [] |
|
35 |
days_done = [] |
|
36 |
year_node.childrens.append(month_node) |
|
37 |
||
38 |
if not date.day in days_done: |
|
39 |
days_done.append(date.day) |
|
40 |
day_node = NavigationNode(datetime.strftime(date, '%d'), |
|
41 |
reverse('news_archive_day', kwargs=dict( |
|
42 |
year=date.year, |
|
43 |
month=datetime.strftime(date, '%m'), |
|
44 |
day=datetime.strftime(date, '%d')))) |
|
45 |
day_node.childrens = [] |
|
46 |
slug_done = [] |
|
47 |
month_node.childrens.append(day_node) |
|
48 |
||
49 |
if not item.slug in slug_done: |
|
50 |
slug_done.append(item.slug) |
|
51 |
item_node = NavigationNode(item.title, item.get_absolute_url()) |
|
52 |
item_node.childrens = [] |
|
53 |
day_node.childrens.append(item_node) |
|
54 |
||
55 |
return res |
|
56 |
Up to file-list cmsplugin_news/templates/cmsplugin_news/news_archive.html:
1 |
<h1>Latest news</h1> |
|
2 |
||
3 |
{% for object in latest %} |
|
4 |
<p><strong>{{ object.title }}</strong><br/><a href="{{ object.get_absolute_url }}">Read more</a></p> |
|
5 |
{% endfor %} |
Up to file-list cmsplugin_news/templates/cmsplugin_news/news_archive_day.html:
1 |
<h1>News for {{ day }}</h1> |
|
2 |
||
3 |
<ul> |
|
4 |
{% for object in object_list %} |
|
5 |
<li><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></li> |
|
6 |
{% empty %} |
|
7 |
<li>No news for this day</li> |
|
8 |
{% endfor %} |
|
9 |
</ul> |
Up to file-list cmsplugin_news/templates/cmsplugin_news/news_archive_month.html:
1 |
<h1>News for {{ month }}</h1> |
|
2 |
||
3 |
<ul> |
|
4 |
{% for object in object_list %} |
|
5 |
<li><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></li> |
|
6 |
{% empty %} |
|
7 |
<li>No news for this month</li> |
|
8 |
{% endfor %} |
|
9 |
</ul> |
Up to file-list cmsplugin_news/templates/cmsplugin_news/news_archive_year.html:
1 |
<h1>News months</h1> |
|
2 |
||
3 |
<ul> |
|
4 |
{% for month in datelist %} |
|
5 |
<li>{{ month }}</li> |
|
6 |
{% endfor %} |
|
7 |
</ul> |
Up to file-list cmsplugin_news/templates/cmsplugin_news/news_detail.html:
1 |
<h1>{{ object.title }}</h1> |
|
2 |
||
3 |
<p><span class="date">{{ object.pub_date }}</span><br/> |
|
4 |
{{ object.content }} |
|
5 |
</p> |
|
6 |
Up to file-list cmsplugin_news/tests.py:
1 |
""" |
|
2 |
This file demonstrates two different styles of tests (one doctest and one |
|
3 |
unittest). These will both pass when you run "manage.py test". |
|
4 |
||
5 |
Replace these with more appropriate tests for your application. |
|
6 |
""" |
|
7 |
||
8 |
from django.test import TestCase |
|
9 |
||
10 |
class SimpleTest(TestCase): |
|
11 |
def test_basic_addition(self): |
|
12 |
""" |
|
13 |
Tests that 1 + 1 always equals 2. |
|
14 |
""" |
|
15 |
self.failUnlessEqual(1 + 1, 2) |
|
16 |
||
17 |
__test__ = {"doctest": """ |
|
18 |
Another way to test that 1 + 1 is equal to 2. |
|
19 |
||
20 |
>>> 1 + 1 == 2 |
|
21 |
True |
|
22 |
"""} |
|
23 |
Up to file-list cmsplugin_news/urls.py:
1 |
from django.conf.urls.defaults import * |
|
2 |
||
3 |
from cmsplugin_news.models import News |
|
4 |
||
5 |
news_info_dict = { |
|
6 |
'queryset': News.published.all(), |
|
7 |
'date_field': 'pub_date', |
|
8 |
} |
|
9 |
||
10 |
news_info_month_dict = { |
|
11 |
'queryset': News.published.all(), |
|
12 |
'date_field': 'pub_date', |
|
13 |
'month_format': '%m', |
|
14 |
} |
|
15 |
||
16 |
urlpatterns = patterns('django.views.generic.date_based', |
|
17 |
(r'^$', |
|
18 |
'archive_index', news_info_dict, 'news_archive_index'), |
|
19 |
||
20 |
(r'^(?P<year>\d{4})/$', |
|
21 |
'archive_year', news_info_dict, 'news_archive_year'), |
|
22 |
||
23 |
(r'^(?P<year>\d{4})/(?P<month>\d{2})/$', |
|
24 |
'archive_month', news_info_month_dict, 'news_archive_month'), |
|
25 |
||
26 |
(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', |
|
27 |
'archive_day', news_info_month_dict, 'news_archive_day'), |
|
28 |
||
29 |
(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[-\w]+)/$', |
|
30 |
'object_detail', news_info_month_dict, 'news_detail'), |
|
31 |
) |
|
32 |
Up to file-list cmsplugin_news/views.py:
1 |
# Create your views here. |
