Merge pull request #158 from nephila/feature/sitemap_improvement
Improve sitemap
This commit is contained in:
commit
72d70411ac
9 changed files with 187 additions and 10 deletions
|
@ -3,6 +3,12 @@
|
|||
History
|
||||
-------
|
||||
|
||||
0.6.1 (2015-10-31)
|
||||
++++++++++++++++++
|
||||
|
||||
* Improve toolbar: add all languages for each post
|
||||
* Improve toolbar: add per-apphook configurable changefreq, priority
|
||||
|
||||
0.6.0 (2015-10-30)
|
||||
++++++++++++++++++
|
||||
|
||||
|
|
72
README.rst
72
README.rst
|
@ -63,8 +63,11 @@ Features
|
|||
* Multisite support (posts can be visible in one or more Django sites on the
|
||||
same project)
|
||||
* Per-Apphook configuration
|
||||
* Configurable permalinks
|
||||
* Configurable django CMS menu support
|
||||
* Per-Apphook templates set
|
||||
* Auto Apphook setup
|
||||
* Django sitemap framework support
|
||||
* Support for django CMS 3.2+ Wizard
|
||||
* Haystack index support
|
||||
|
||||
|
@ -163,7 +166,7 @@ suited for your deployment.
|
|||
|
||||
* To start your blog you need to use `AppHooks from django CMS <http://django-cms.readthedocs.org/en/support-3.0.x/how_to/apphooks.html>`_
|
||||
to add the blog to a django CMS page; this step is not required when using
|
||||
**Auto setup** (see below):
|
||||
`Auto setup <auto_setup>`_:
|
||||
|
||||
* Create a new django CMS page
|
||||
* Go to Advanced settings and select Blog from the Application selector and
|
||||
|
@ -206,6 +209,16 @@ like the following in the project settings::
|
|||
|
||||
And change ``post/`` with the desired prefix.
|
||||
|
||||
Menu
|
||||
++++
|
||||
|
||||
``djangocms_blog`` provides support for django CMS menu framework.
|
||||
|
||||
By default all the categories and posts are added to the menu, in a hierarcical structure.
|
||||
|
||||
Is it possibile to configure per Apphook, whether the menu includes post and categories
|
||||
(the default), only categorie, only posts or no item.
|
||||
|
||||
Templates
|
||||
+++++++++
|
||||
|
||||
|
@ -226,6 +239,8 @@ To use this feature provide a directory name in **Template prefix** field in
|
|||
the **Apphook configuration** admin (in *Layout* section): it will be the
|
||||
root of your custom templates set.
|
||||
|
||||
.. _auto_setup:
|
||||
|
||||
Auto setup
|
||||
++++++++++
|
||||
|
||||
|
@ -249,6 +264,44 @@ The auto setup is execute once for each server start but it will skip any
|
|||
action if a ``BlogConfig`` instance is found.
|
||||
|
||||
|
||||
Sitemap
|
||||
+++++++
|
||||
|
||||
``djangocms_blog`` provides a sitemap for improved SEO indexing.
|
||||
Sitemap returns all the published posts in all the languages each post is available.
|
||||
|
||||
The changefreq and priority is configurable per-apphook (see ``BLOG_SITEMAP_*`` in
|
||||
`Global settings <settings>`_).
|
||||
|
||||
To add the blog Sitemap, add the following code to the project ``urls.py``::
|
||||
|
||||
|
||||
from cms.sitemaps import CMSSitemap
|
||||
from djangocms_blog.sitemaps import BlogSitemap
|
||||
|
||||
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
...
|
||||
url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',
|
||||
{'sitemaps': {
|
||||
'cmspages': CMSSitemap, 'blog': BlogSitemap,
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
django CMS 3.2+ Wizard
|
||||
++++++++++++++++++++++
|
||||
|
||||
django CMS 3.2+ provides a content creation wizard that allows to quickly created supported
|
||||
content types, such as blog posts.
|
||||
|
||||
For each configured Apphook, a content type is added to the wizard.
|
||||
|
||||
|
||||
.. _settings:
|
||||
|
||||
Global Settings
|
||||
---------------
|
||||
* BLOG_IMAGE_THUMBNAIL_SIZE: Size of the main image when shown on the post
|
||||
|
@ -292,8 +345,6 @@ Global Settings
|
|||
* BLOG_USE_PLACEHOLDER: Post content is managed via placeholder;
|
||||
if ``False`` a simple HTMLField is used; (default: ``True``)
|
||||
* BLOG_MULTISITE: Add support for multisite setup; (default: ``True``)
|
||||
* BLOG_MENU_TYPE: Structure of the Blog menu;
|
||||
(default: ``Posts and Categories``)
|
||||
* BLOG_AUTHOR_DEFAULT: Use a default if not specified; if set to ``True`` the
|
||||
current user is set as the default author, if set to ``False`` no default
|
||||
author is set, if set to a string the user with the provided username is
|
||||
|
@ -311,6 +362,19 @@ Global Settings
|
|||
(default: ``Blog``)
|
||||
* BLOG_AUTO_APP_TITLE: Title of the ``BlogConfig`` instance created by
|
||||
**Auto setup**; (default: ``Blog``)
|
||||
* BLOG_SITEMAP_PRIORITY_DEFAULT: Default priority for sitemap items; (default: ``0.5``)
|
||||
* BLOG_SITEMAP_CHANGEFREQ: List for available changefreqs for sitemap items; (default: **always**,
|
||||
**hourly**, **daily**, **weekly**, **monthly**, **yearly**, **never**)
|
||||
* BLOG_SITEMAP_CHANGEFREQ_DEFAULT: Default changefreq for sitemap items; (default: ``monthly``)
|
||||
|
||||
Read-only settings
|
||||
++++++++++++++++++
|
||||
|
||||
* BLOG_MENU_TYPES: Available structures of the Blog menu; (default list **Posts and Categories**,
|
||||
**Categories only**, **Posts only**, **None**)
|
||||
* BLOG_MENU_TYPE: Structure of the Blog menu;
|
||||
(default: ``Posts and Categories``)
|
||||
|
||||
|
||||
Per-Apphook settings
|
||||
--------------------
|
||||
|
@ -327,6 +391,8 @@ Per-Apphook settings
|
|||
* Paginate sizePer-Apphook setting for BLOG_PAGINATION;
|
||||
* Template prefix: Alternative directory to load the blog templates from;
|
||||
* Menu structure: Per-Apphook setting for BLOG_MENU_TYPE
|
||||
* Sitemap changefreq: Per-Apphook setting for BLOG_SITEMAP_CHANGEFREQ_DEFAULT
|
||||
* Sitemap priority: Per-Apphook setting for BLOG_SITEMAP_PRIORITY_DEFAULT
|
||||
* Object type: Per-Apphook setting for BLOG_TYPE
|
||||
* Facebook type: Per-Apphook setting for BLOG_FB_TYPE
|
||||
* Facebook application ID: Per-Apphook setting for BLOG_FB_APP_ID
|
||||
|
|
|
@ -14,6 +14,7 @@ HELPER_SETTINGS = dict(
|
|||
'meta',
|
||||
'meta_mixin',
|
||||
'easy_thumbnails',
|
||||
'django.contrib.sitemaps',
|
||||
'djangocms_text_ckeditor',
|
||||
'cmsplugin_filer_image',
|
||||
'taggit',
|
||||
|
|
|
@ -149,6 +149,12 @@ class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin):
|
|||
),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Sitemap', {
|
||||
'fields': (
|
||||
'config.sitemap_changefreq', 'config.sitemap_priority',
|
||||
),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
('Meta', {
|
||||
'fields': (
|
||||
'config.object_type',
|
||||
|
|
|
@ -62,6 +62,17 @@ class BlogConfigForm(AppDataForm):
|
|||
choices=get_setting('MENU_TYPES'), initial=MENU_TYPE_COMPLETE,
|
||||
help_text=_('Structure of the django CMS menu')
|
||||
)
|
||||
sitemap_changefreq = forms.ChoiceField(
|
||||
label=_('Sitemap changefreq'), required=True,
|
||||
choices=get_setting('SITEMAP_CHANGEFREQ'),
|
||||
initial=get_setting('SITEMAP_CHANGEFREQ_DEFAULT'),
|
||||
help_text=_('Changefreq attribute for sidebar items')
|
||||
)
|
||||
sitemap_priority = forms.CharField(
|
||||
label=_('Sitemap priority'), required=True,
|
||||
initial=get_setting('SITEMAP_PRIORITY_DEFAULT'),
|
||||
help_text=_('Priority attribute for sidebar items')
|
||||
)
|
||||
object_type = forms.ChoiceField(
|
||||
label=_('Object type'), required=False,
|
||||
choices=get_setting('TYPES'), initial=get_setting('TYPE')
|
||||
|
|
|
@ -30,6 +30,15 @@ def get_setting(name):
|
|||
(MENU_TYPE_POSTS, _('Posts only')),
|
||||
(MENU_TYPE_NONE, _('None')),
|
||||
)
|
||||
SITEMAP_CHANGEFREQ_LIST = (
|
||||
('always', _('always')),
|
||||
('hourly', _('hourly')),
|
||||
('daily', _('daily')),
|
||||
('weekly', _('weekly')),
|
||||
('monthly', _('monthly')),
|
||||
('yearly', _('yearly')),
|
||||
('never', _('never')),
|
||||
)
|
||||
default = {
|
||||
'BLOG_IMAGE_THUMBNAIL_SIZE': getattr(settings, 'BLOG_IMAGE_THUMBNAIL_SIZE', {
|
||||
'size': '120x120',
|
||||
|
@ -48,7 +57,6 @@ def get_setting(name):
|
|||
'BLOG_POSTS_LIST_TRUNCWORDS_COUNT': getattr(
|
||||
settings, 'BLOG_POSTS_LIST_TRUNCWORDS_COUNT', 100
|
||||
),
|
||||
'BLOG_MENU_TYPE': MENU_TYPES,
|
||||
'BLOG_MENU_TYPES': MENU_TYPES,
|
||||
'BLOG_TYPE': getattr(settings, 'BLOG_TYPE', 'Article'),
|
||||
'BLOG_TYPES': meta_settings.OBJECT_TYPES,
|
||||
|
@ -72,7 +80,9 @@ def get_setting(name):
|
|||
'BLOG_MULTISITE': getattr(settings, 'BLOG_MULTISITE', True),
|
||||
'BLOG_AUTHOR_DEFAULT': getattr(settings, 'BLOG_AUTHOR_DEFAULT', True),
|
||||
'BLOG_DEFAULT_PUBLISHED': getattr(settings, 'BLOG_DEFAULT_PUBLISHED', False),
|
||||
'BLOG_AVAILABLE_PERMALINK_STYLES': getattr(settings, 'BLOG_AVAILABLE_PERMALINK_STYLES', PERMALINKS), # NOQA
|
||||
'BLOG_AVAILABLE_PERMALINK_STYLES': getattr(
|
||||
settings, 'BLOG_AVAILABLE_PERMALINK_STYLES', PERMALINKS
|
||||
),
|
||||
'BLOG_PERMALINK_URLS': getattr(settings, 'BLOG_PERMALINK_URLS', PERMALINKS_URLS),
|
||||
'BLOG_DEFAULT_OBJECT_NAME': getattr(settings, 'BLOG_DEFAULT_OBJECT_NAME', 'Article'),
|
||||
|
||||
|
@ -82,6 +92,14 @@ def get_setting(name):
|
|||
'BLOG_AUTO_APP_TITLE': getattr(settings, 'BLOG_AUTO_APP_TITLE', 'Blog'),
|
||||
'BLOG_AUTO_NAMESPACE': getattr(settings, 'BLOG_AUTO_NAMESPACE', 'Blog'),
|
||||
|
||||
'BLOG_SITEMAP_PRIORITY_DEFAULT': getattr(settings, 'BLOG_SITEMAP_PRIORITY_DEFAULT', '0.5'),
|
||||
'BLOG_SITEMAP_CHANGEFREQ': getattr(
|
||||
settings, 'BLOG_SITEMAP_CHANGEFREQ', SITEMAP_CHANGEFREQ_LIST
|
||||
),
|
||||
'BLOG_SITEMAP_CHANGEFREQ_DEFAULT': getattr(
|
||||
settings, 'BLOG_SITEMAP_CHANGEFREQ_DEFAULT', 'monthly'
|
||||
),
|
||||
|
||||
'BLOG_ENABLE_SEARCH': getattr(settings, 'BLOG_ENABLE_SEARCH', True),
|
||||
}
|
||||
return default['BLOG_%s' % name]
|
||||
|
|
|
@ -1,17 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import, print_function, unicode_literals
|
||||
|
||||
from cms.utils import get_language_list
|
||||
from django.contrib.sitemaps import Sitemap
|
||||
from parler.utils.context import smart_override
|
||||
|
||||
from ..models import Post
|
||||
from ..settings import get_setting
|
||||
|
||||
|
||||
class BlogSitemap(Sitemap):
|
||||
changefreq = 'never'
|
||||
priority = 0.5
|
||||
|
||||
def priority(self, obj):
|
||||
if obj and obj.app_config:
|
||||
return obj.app_config.sitemap_priority
|
||||
return get_setting('SITEMAP_PRIORITY_DEFAULT')
|
||||
|
||||
def changefreq(self, obj):
|
||||
if obj and obj.app_config:
|
||||
return obj.app_config.sitemap_changefreq
|
||||
return get_setting('SITEMAP_CHANGEFREQ_DEFAULT')
|
||||
|
||||
def location(self, obj):
|
||||
with smart_override(obj.get_current_language()):
|
||||
return obj.get_absolute_url(obj.get_current_language())
|
||||
|
||||
def items(self):
|
||||
return Post.objects.published()
|
||||
items = []
|
||||
for lang in get_language_list():
|
||||
items.extend(Post.objects.translated(lang).language(lang).published())
|
||||
return items
|
||||
|
||||
def lastmod(self, obj):
|
||||
return obj.date_modified
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|||
|
||||
import sys
|
||||
|
||||
from cms.sitemaps import CMSSitemap
|
||||
from cms.utils.conf import get_cms_setting
|
||||
from django.conf import settings
|
||||
from django.conf.urls import include, patterns, url
|
||||
|
@ -10,6 +11,8 @@ from django.conf.urls.i18n import i18n_patterns
|
|||
from django.contrib import admin
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
|
||||
from djangocms_blog.sitemaps import BlogSitemap
|
||||
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = patterns(
|
||||
|
@ -20,6 +23,11 @@ urlpatterns = patterns(
|
|||
{'document_root': get_cms_setting('MEDIA_ROOT'), 'show_indexes': True}),
|
||||
url(r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
|
||||
url(r'^taggit_autosuggest/', include('taggit_autosuggest.urls')),
|
||||
url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',
|
||||
{'sitemaps': {
|
||||
'cmspages': CMSSitemap, 'blog': BlogSitemap,
|
||||
}
|
||||
}),
|
||||
)
|
||||
|
||||
urlpatterns += staticfiles_urlpatterns()
|
||||
|
|
|
@ -17,6 +17,7 @@ from parler.utils.context import smart_override, switch_language
|
|||
|
||||
from djangocms_blog.feeds import LatestEntriesFeed, TagFeed
|
||||
from djangocms_blog.models import BLOG_CURRENT_NAMESPACE
|
||||
from djangocms_blog.settings import get_setting
|
||||
from djangocms_blog.sitemaps import BlogSitemap
|
||||
from djangocms_blog.views import (
|
||||
AuthorEntriesView, CategoryEntriesView, PostArchiveView, PostDetailView, PostListView,
|
||||
|
@ -339,6 +340,7 @@ class ViewTest(BaseTest):
|
|||
|
||||
def test_sitemap(self):
|
||||
posts = self.get_posts()
|
||||
self.get_pages()
|
||||
posts[0].tags.add('tag 1', 'tag 2', 'tag 3', 'tag 4')
|
||||
posts[0].save()
|
||||
posts[1].tags.add('tag 6', 'tag 2', 'tag 5', 'tag 8')
|
||||
|
@ -347,9 +349,50 @@ class ViewTest(BaseTest):
|
|||
posts[0].set_current_language('en')
|
||||
|
||||
sitemap = BlogSitemap()
|
||||
self.assertEqual(sitemap.items().count(), 3)
|
||||
self.assertEqual(len(sitemap.items()), 6)
|
||||
for item in sitemap.items():
|
||||
self.assertTrue(sitemap.lastmod(item).date(), now().today())
|
||||
self.assertEqual(sitemap.lastmod(item).date(), now().date())
|
||||
self.assertEqual(
|
||||
sitemap.priority(item), get_setting('SITEMAP_PRIORITY_DEFAULT')
|
||||
)
|
||||
self.assertEqual(
|
||||
sitemap.changefreq(item), get_setting('SITEMAP_CHANGEFREQ_DEFAULT')
|
||||
)
|
||||
with smart_override(item.get_current_language()):
|
||||
self.assertEqual(
|
||||
sitemap.location(item), item.get_absolute_url()
|
||||
)
|
||||
|
||||
def test_sitemap_config(self):
|
||||
posts = self.get_posts()
|
||||
self.app_config_1.app_data.config.sitemap_changefreq = 'daily'
|
||||
self.app_config_1.app_data.config.sitemap_priority = '0.2'
|
||||
self.app_config_1.save()
|
||||
|
||||
sitemap = BlogSitemap()
|
||||
self.assertEqual(len(sitemap.items()), 4)
|
||||
for item in sitemap.items():
|
||||
self.assertEqual(sitemap.lastmod(item).date(), now().date())
|
||||
if item.app_config == self.app_config_1:
|
||||
self.assertEqual(
|
||||
sitemap.priority(item), '0.2'
|
||||
)
|
||||
self.assertEqual(
|
||||
sitemap.changefreq(item), 'daily'
|
||||
)
|
||||
else:
|
||||
self.assertEqual(
|
||||
sitemap.priority(item), get_setting('SITEMAP_PRIORITY_DEFAULT')
|
||||
)
|
||||
self.assertEqual(
|
||||
sitemap.changefreq(item), get_setting('SITEMAP_CHANGEFREQ_DEFAULT')
|
||||
)
|
||||
self.assertEqual(
|
||||
sitemap.priority(None), get_setting('SITEMAP_PRIORITY_DEFAULT')
|
||||
)
|
||||
self.assertEqual(
|
||||
sitemap.changefreq(None), get_setting('SITEMAP_CHANGEFREQ_DEFAULT')
|
||||
)
|
||||
|
||||
def test_templates(self):
|
||||
posts = self.get_posts()
|
||||
|
|
Loading…
Reference in a new issue