The blog application for django CMS providing multilingual blog functionality with advanced content management features
—
Automated RSS feed generation and sitemap integration for SEO optimization with multilingual support and customizable output formats.
Comprehensive RSS feed system for blog content distribution.
class LatestEntriesFeed(Feed):
"""
RSS feed for latest blog entries.
Features:
- Configurable number of items
- Multilingual content support
- App configuration filtering
- Custom feed metadata
- Rich content support with images and media
"""
feed_type: Type[Rss201rev2Feed] = Rss201rev2Feed
feed_items_number: int = get_setting("FEED_LATEST_ITEMS")
def __call__(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
"""Handle feed request with app configuration context."""
def get_object(self, request: HttpRequest, *args, **kwargs) -> BlogConfig:
"""Get blog configuration for feed context."""
def title(self, obj: BlogConfig) -> str:
"""Return feed title based on configuration."""
def link(self, obj: BlogConfig) -> str:
"""Return feed link URL."""
def description(self, obj: BlogConfig) -> str:
"""Return feed description."""
def items(self, obj: BlogConfig) -> QuerySet:
"""
Return published posts for feed.
Returns:
QuerySet of published posts filtered by:
- Publication status
- App configuration
- RSS inclusion setting
- Language context
- Site filtering (if multisite)
"""
def item_title(self, item: Post) -> str:
"""Return post title for feed item."""
def item_description(self, item: Post) -> str:
"""Return post description/content for feed item."""
def item_link(self, item: Post) -> str:
"""Return post URL for feed item."""
def item_author_name(self, item: Post) -> str:
"""Return post author name."""
def item_author_email(self, item: Post) -> str:
"""Return post author email."""
def item_pubdate(self, item: Post) -> datetime:
"""Return post publication date."""
def item_updateddate(self, item: Post) -> datetime:
"""Return post last modified date."""
def item_categories(self, item: Post) -> List[str]:
"""Return post categories as feed categories."""
def item_enclosure_url(self, item: Post) -> Optional[str]:
"""Return main image URL as enclosure."""
def item_enclosure_length(self, item: Post) -> Optional[int]:
"""Return main image file size."""
def item_enclosure_mime_type(self, item: Post) -> Optional[str]:
"""Return main image MIME type."""SEO-optimized sitemap generation for blog content.
class BlogSitemap(Sitemap):
"""
Sitemap generator for blog posts.
Features:
- Multilingual URL generation
- Configurable priority and change frequency
- App configuration filtering
- Automatic URL validation
- Cache-optimized URL generation
"""
def __init__(self, *args, **kwargs) -> None:
"""Initialize sitemap with URL cache."""
def priority(self, obj: Post) -> float:
"""
Return sitemap priority for post.
Uses app configuration priority or default setting.
Range: 0.0 to 1.0
"""
def changefreq(self, obj: Post) -> str:
"""
Return change frequency for post.
Options: 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'
Uses app configuration setting or default.
"""
def location(self, obj: Post) -> str:
"""Return absolute URL for post in current language."""
def items(self) -> List[Post]:
"""
Return all published posts across all languages.
Features:
- Multi-language support
- URL validation to exclude posts without valid URLs
- App configuration filtering
- Publication status filtering
"""
def lastmod(self, obj: Post) -> datetime:
"""Return last modification date for post."""Specialized feed types for tag-based and Facebook Instant Articles content.
class TagFeed(LatestEntriesFeed):
"""
RSS feed for posts filtered by specific tag.
Features:
- Tag-specific post filtering
- Dynamic title and description based on tag
- Same feed functionality as LatestEntriesFeed
"""
def get_object(self, request: HttpRequest, tag: str) -> Dict[str, Any]:
"""Get tag and blog configuration for feed context."""
def title(self, obj: Dict[str, Any]) -> str:
"""Return feed title with tag name."""
def description(self, obj: Dict[str, Any]) -> str:
"""Return feed description for tag."""
def items(self, obj: Dict[str, Any]) -> QuerySet:
"""Return posts filtered by tag."""
class FBInstantArticles(LatestEntriesFeed):
"""
Facebook Instant Articles feed with custom XML format.
Features:
- Facebook Instant Articles XML format
- Custom RSS elements for Facebook compatibility
- Media content optimization
- Enhanced article metadata
"""
content_type: str = 'application/rss+xml; charset=utf-8'
def items(self, obj: BlogConfig) -> QuerySet:
"""Return posts optimized for Facebook Instant Articles."""
def item_extra_kwargs(self, item: Post) -> Dict[str, Any]:
"""Add Facebook-specific metadata to feed items."""Base classes and utilities for creating custom feeds.
# Custom feed class example structure
class CustomBlogFeed(LatestEntriesFeed):
"""
Base structure for custom blog feeds.
Override methods to customize:
- title(): Feed title
- description(): Feed description
- items(): Item selection and filtering
- item_title(): Individual item titles
- item_description(): Individual item content
"""
def items(self, obj: BlogConfig) -> QuerySet:
"""Custom item filtering logic."""
def item_extra_kwargs(self, item: Post) -> Dict[str, Any]:
"""Add custom attributes to feed items."""# URL configuration for feeds and sitemaps
from django.urls import path, include
from djangocms_blog.feeds import LatestEntriesFeed
from djangocms_blog.sitemaps import BlogSitemap
urlpatterns = [
# RSS feed URL
path('blog/feed/', LatestEntriesFeed(), name='blog-feed'),
# Include blog URLs (includes feed URLs)
path('blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
]
# Sitemap configuration in main urls.py
from django.contrib.sitemaps.views import sitemap
from djangocms_blog.sitemaps import BlogSitemap
sitemaps = {
'blog': BlogSitemap,
}
urlpatterns += [
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
]
# Custom feed creation
from djangocms_blog.feeds import LatestEntriesFeed
from djangocms_blog.models import Post
class FeaturedPostsFeed(LatestEntriesFeed):
"""RSS feed for featured posts only."""
def title(self, obj):
return f"{obj.app_title} - Featured Posts"
def description(self, obj):
return f"Featured posts from {obj.app_title}"
def items(self, obj):
"""Return only featured posts."""
return Post.objects.published().filter(
app_config=obj,
featured=True,
include_in_rss=True
).order_by('-date_published')[:self.feed_items_number]
class CategoryFeed(LatestEntriesFeed):
"""RSS feed for specific category."""
def get_object(self, request, category_slug):
"""Get category and config for feed."""
from djangocms_blog.models import BlogCategory
from aldryn_apphooks_config.utils import get_app_instance
namespace, config = get_app_instance(request)
category = BlogCategory.objects.translated().get(
slug=category_slug,
app_config=config
)
return {'config': config, 'category': category}
def title(self, obj):
return f"{obj['config'].app_title} - {obj['category'].name}"
def items(self, obj):
"""Return posts in specific category."""
return Post.objects.published().filter(
app_config=obj['config'],
categories=obj['category'],
include_in_rss=True
).order_by('-date_published')[:self.feed_items_number]
# Custom feed with media enclosures
class MediaEnhancedFeed(LatestEntriesFeed):
"""Feed with enhanced media support."""
def item_extra_kwargs(self, item):
"""Add custom media information."""
kwargs = super().item_extra_kwargs(item)
# Add main image as enclosure
if item.main_image:
kwargs.update({
'enclosure': {
'url': item.main_image.url,
'length': str(item.main_image.size),
'type': 'image/jpeg' # or detect from file
}
})
return kwargs
def item_description(self, item):
"""Enhanced description with media."""
description = super().item_description(item)
# Add main image to description
if item.main_image:
img_tag = f'<img src="{item.main_image.url}" alt="{item.title}" />'
description = f"{img_tag}<br/>{description}"
return description
# Custom sitemap with additional URLs
from django.contrib.sitemaps import Sitemap
from djangocms_blog.models import BlogCategory
class BlogCategorySitemap(Sitemap):
"""Sitemap for blog categories."""
priority = 0.6
changefreq = 'weekly'
def items(self):
"""Return all published categories."""
return BlogCategory.objects.translated().published()
def location(self, obj):
"""Return category URL."""
return obj.get_absolute_url()
def lastmod(self, obj):
"""Return last modification based on latest post in category."""
latest_post = Post.objects.published().filter(
categories=obj
).order_by('-date_modified').first()
return latest_post.date_modified if latest_post else None
# Multiple sitemaps registration
sitemaps = {
'blog_posts': BlogSitemap,
'blog_categories': BlogCategorySitemap,
}
# Feed autodiscovery in templates
# Add to base template <head> section:
# {% load cms_tags %}
# {% page_url 'posts-latest-feed' as feed_url %}
# <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="{{ feed_url }}">
# Settings customization
# In Django settings.py:
BLOG_FEED_LATEST_ITEMS = 20
BLOG_FEED_ENABLE = True
BLOG_SITEMAP_PRIORITY_DEFAULT = 0.7
BLOG_SITEMAP_CHANGEFREQ_DEFAULT = 'weekly'
# Per-configuration customization
# In BlogConfig app_data:
{
'feed_latest_items': 15,
'sitemap_priority': 0.8,
'sitemap_changefreq': 'daily'
}
# Conditional feed inclusion
class ConditionalFeed(LatestEntriesFeed):
"""Feed that respects post RSS inclusion setting."""
def items(self, obj):
"""Only include posts marked for RSS."""
return super().items(obj).filter(include_in_rss=True)
# Feed with custom namespace support
from django.urls import path
# Per-apphook feed URLs
app_name = 'blog_feeds'
urlpatterns = [
path('feed/', LatestEntriesFeed(), name='latest'),
path('featured/', FeaturedPostsFeed(), name='featured'),
path('category/<slug:category_slug>/', CategoryFeed(), name='category'),
]
# Access in templates:
# {% url 'blog_feeds:latest' %}
# {% url 'blog_feeds:featured' %}
# {% url 'blog_feeds:category' category.slug %}Install with Tessl CLI
npx tessl i tessl/pypi-djangocms-blog