0
# Feeds and Sitemaps
1
2
Automated RSS feed generation and sitemap integration for SEO optimization with multilingual support and customizable output formats.
3
4
## Capabilities
5
6
### RSS Feed Generation
7
8
Comprehensive RSS feed system for blog content distribution.
9
10
```python { .api }
11
class LatestEntriesFeed(Feed):
12
"""
13
RSS feed for latest blog entries.
14
15
Features:
16
- Configurable number of items
17
- Multilingual content support
18
- App configuration filtering
19
- Custom feed metadata
20
- Rich content support with images and media
21
"""
22
23
feed_type: Type[Rss201rev2Feed] = Rss201rev2Feed
24
feed_items_number: int = get_setting("FEED_LATEST_ITEMS")
25
26
def __call__(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
27
"""Handle feed request with app configuration context."""
28
29
def get_object(self, request: HttpRequest, *args, **kwargs) -> BlogConfig:
30
"""Get blog configuration for feed context."""
31
32
def title(self, obj: BlogConfig) -> str:
33
"""Return feed title based on configuration."""
34
35
def link(self, obj: BlogConfig) -> str:
36
"""Return feed link URL."""
37
38
def description(self, obj: BlogConfig) -> str:
39
"""Return feed description."""
40
41
def items(self, obj: BlogConfig) -> QuerySet:
42
"""
43
Return published posts for feed.
44
45
Returns:
46
QuerySet of published posts filtered by:
47
- Publication status
48
- App configuration
49
- RSS inclusion setting
50
- Language context
51
- Site filtering (if multisite)
52
"""
53
54
def item_title(self, item: Post) -> str:
55
"""Return post title for feed item."""
56
57
def item_description(self, item: Post) -> str:
58
"""Return post description/content for feed item."""
59
60
def item_link(self, item: Post) -> str:
61
"""Return post URL for feed item."""
62
63
def item_author_name(self, item: Post) -> str:
64
"""Return post author name."""
65
66
def item_author_email(self, item: Post) -> str:
67
"""Return post author email."""
68
69
def item_pubdate(self, item: Post) -> datetime:
70
"""Return post publication date."""
71
72
def item_updateddate(self, item: Post) -> datetime:
73
"""Return post last modified date."""
74
75
def item_categories(self, item: Post) -> List[str]:
76
"""Return post categories as feed categories."""
77
78
def item_enclosure_url(self, item: Post) -> Optional[str]:
79
"""Return main image URL as enclosure."""
80
81
def item_enclosure_length(self, item: Post) -> Optional[int]:
82
"""Return main image file size."""
83
84
def item_enclosure_mime_type(self, item: Post) -> Optional[str]:
85
"""Return main image MIME type."""
86
```
87
88
### Sitemap Generation
89
90
SEO-optimized sitemap generation for blog content.
91
92
```python { .api }
93
class BlogSitemap(Sitemap):
94
"""
95
Sitemap generator for blog posts.
96
97
Features:
98
- Multilingual URL generation
99
- Configurable priority and change frequency
100
- App configuration filtering
101
- Automatic URL validation
102
- Cache-optimized URL generation
103
"""
104
105
def __init__(self, *args, **kwargs) -> None:
106
"""Initialize sitemap with URL cache."""
107
108
def priority(self, obj: Post) -> float:
109
"""
110
Return sitemap priority for post.
111
112
Uses app configuration priority or default setting.
113
Range: 0.0 to 1.0
114
"""
115
116
def changefreq(self, obj: Post) -> str:
117
"""
118
Return change frequency for post.
119
120
Options: 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never'
121
Uses app configuration setting or default.
122
"""
123
124
def location(self, obj: Post) -> str:
125
"""Return absolute URL for post in current language."""
126
127
def items(self) -> List[Post]:
128
"""
129
Return all published posts across all languages.
130
131
Features:
132
- Multi-language support
133
- URL validation to exclude posts without valid URLs
134
- App configuration filtering
135
- Publication status filtering
136
"""
137
138
def lastmod(self, obj: Post) -> datetime:
139
"""Return last modification date for post."""
140
```
141
142
### Additional Feed Types
143
144
Specialized feed types for tag-based and Facebook Instant Articles content.
145
146
```python { .api }
147
class TagFeed(LatestEntriesFeed):
148
"""
149
RSS feed for posts filtered by specific tag.
150
151
Features:
152
- Tag-specific post filtering
153
- Dynamic title and description based on tag
154
- Same feed functionality as LatestEntriesFeed
155
"""
156
157
def get_object(self, request: HttpRequest, tag: str) -> Dict[str, Any]:
158
"""Get tag and blog configuration for feed context."""
159
160
def title(self, obj: Dict[str, Any]) -> str:
161
"""Return feed title with tag name."""
162
163
def description(self, obj: Dict[str, Any]) -> str:
164
"""Return feed description for tag."""
165
166
def items(self, obj: Dict[str, Any]) -> QuerySet:
167
"""Return posts filtered by tag."""
168
169
class FBInstantArticles(LatestEntriesFeed):
170
"""
171
Facebook Instant Articles feed with custom XML format.
172
173
Features:
174
- Facebook Instant Articles XML format
175
- Custom RSS elements for Facebook compatibility
176
- Media content optimization
177
- Enhanced article metadata
178
"""
179
180
content_type: str = 'application/rss+xml; charset=utf-8'
181
182
def items(self, obj: BlogConfig) -> QuerySet:
183
"""Return posts optimized for Facebook Instant Articles."""
184
185
def item_extra_kwargs(self, item: Post) -> Dict[str, Any]:
186
"""Add Facebook-specific metadata to feed items."""
187
```
188
189
### Feed Customization
190
191
Base classes and utilities for creating custom feeds.
192
193
```python { .api }
194
# Custom feed class example structure
195
class CustomBlogFeed(LatestEntriesFeed):
196
"""
197
Base structure for custom blog feeds.
198
199
Override methods to customize:
200
- title(): Feed title
201
- description(): Feed description
202
- items(): Item selection and filtering
203
- item_title(): Individual item titles
204
- item_description(): Individual item content
205
"""
206
207
def items(self, obj: BlogConfig) -> QuerySet:
208
"""Custom item filtering logic."""
209
210
def item_extra_kwargs(self, item: Post) -> Dict[str, Any]:
211
"""Add custom attributes to feed items."""
212
```
213
214
## Feed and Sitemap Usage Examples
215
216
```python
217
# URL configuration for feeds and sitemaps
218
from django.urls import path, include
219
from djangocms_blog.feeds import LatestEntriesFeed
220
from djangocms_blog.sitemaps import BlogSitemap
221
222
urlpatterns = [
223
# RSS feed URL
224
path('blog/feed/', LatestEntriesFeed(), name='blog-feed'),
225
226
# Include blog URLs (includes feed URLs)
227
path('blog/', include('djangocms_blog.urls', namespace='djangocms_blog')),
228
]
229
230
# Sitemap configuration in main urls.py
231
from django.contrib.sitemaps.views import sitemap
232
from djangocms_blog.sitemaps import BlogSitemap
233
234
sitemaps = {
235
'blog': BlogSitemap,
236
}
237
238
urlpatterns += [
239
path('sitemap.xml', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
240
]
241
242
# Custom feed creation
243
from djangocms_blog.feeds import LatestEntriesFeed
244
from djangocms_blog.models import Post
245
246
class FeaturedPostsFeed(LatestEntriesFeed):
247
"""RSS feed for featured posts only."""
248
249
def title(self, obj):
250
return f"{obj.app_title} - Featured Posts"
251
252
def description(self, obj):
253
return f"Featured posts from {obj.app_title}"
254
255
def items(self, obj):
256
"""Return only featured posts."""
257
return Post.objects.published().filter(
258
app_config=obj,
259
featured=True,
260
include_in_rss=True
261
).order_by('-date_published')[:self.feed_items_number]
262
263
class CategoryFeed(LatestEntriesFeed):
264
"""RSS feed for specific category."""
265
266
def get_object(self, request, category_slug):
267
"""Get category and config for feed."""
268
from djangocms_blog.models import BlogCategory
269
from aldryn_apphooks_config.utils import get_app_instance
270
271
namespace, config = get_app_instance(request)
272
category = BlogCategory.objects.translated().get(
273
slug=category_slug,
274
app_config=config
275
)
276
return {'config': config, 'category': category}
277
278
def title(self, obj):
279
return f"{obj['config'].app_title} - {obj['category'].name}"
280
281
def items(self, obj):
282
"""Return posts in specific category."""
283
return Post.objects.published().filter(
284
app_config=obj['config'],
285
categories=obj['category'],
286
include_in_rss=True
287
).order_by('-date_published')[:self.feed_items_number]
288
289
# Custom feed with media enclosures
290
class MediaEnhancedFeed(LatestEntriesFeed):
291
"""Feed with enhanced media support."""
292
293
def item_extra_kwargs(self, item):
294
"""Add custom media information."""
295
kwargs = super().item_extra_kwargs(item)
296
297
# Add main image as enclosure
298
if item.main_image:
299
kwargs.update({
300
'enclosure': {
301
'url': item.main_image.url,
302
'length': str(item.main_image.size),
303
'type': 'image/jpeg' # or detect from file
304
}
305
})
306
307
return kwargs
308
309
def item_description(self, item):
310
"""Enhanced description with media."""
311
description = super().item_description(item)
312
313
# Add main image to description
314
if item.main_image:
315
img_tag = f'<img src="{item.main_image.url}" alt="{item.title}" />'
316
description = f"{img_tag}<br/>{description}"
317
318
return description
319
320
# Custom sitemap with additional URLs
321
from django.contrib.sitemaps import Sitemap
322
from djangocms_blog.models import BlogCategory
323
324
class BlogCategorySitemap(Sitemap):
325
"""Sitemap for blog categories."""
326
327
priority = 0.6
328
changefreq = 'weekly'
329
330
def items(self):
331
"""Return all published categories."""
332
return BlogCategory.objects.translated().published()
333
334
def location(self, obj):
335
"""Return category URL."""
336
return obj.get_absolute_url()
337
338
def lastmod(self, obj):
339
"""Return last modification based on latest post in category."""
340
latest_post = Post.objects.published().filter(
341
categories=obj
342
).order_by('-date_modified').first()
343
344
return latest_post.date_modified if latest_post else None
345
346
# Multiple sitemaps registration
347
sitemaps = {
348
'blog_posts': BlogSitemap,
349
'blog_categories': BlogCategorySitemap,
350
}
351
352
# Feed autodiscovery in templates
353
# Add to base template <head> section:
354
# {% load cms_tags %}
355
# {% page_url 'posts-latest-feed' as feed_url %}
356
# <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="{{ feed_url }}">
357
358
# Settings customization
359
# In Django settings.py:
360
BLOG_FEED_LATEST_ITEMS = 20
361
BLOG_FEED_ENABLE = True
362
BLOG_SITEMAP_PRIORITY_DEFAULT = 0.7
363
BLOG_SITEMAP_CHANGEFREQ_DEFAULT = 'weekly'
364
365
# Per-configuration customization
366
# In BlogConfig app_data:
367
{
368
'feed_latest_items': 15,
369
'sitemap_priority': 0.8,
370
'sitemap_changefreq': 'daily'
371
}
372
373
# Conditional feed inclusion
374
class ConditionalFeed(LatestEntriesFeed):
375
"""Feed that respects post RSS inclusion setting."""
376
377
def items(self, obj):
378
"""Only include posts marked for RSS."""
379
return super().items(obj).filter(include_in_rss=True)
380
381
# Feed with custom namespace support
382
from django.urls import path
383
384
# Per-apphook feed URLs
385
app_name = 'blog_feeds'
386
urlpatterns = [
387
path('feed/', LatestEntriesFeed(), name='latest'),
388
path('featured/', FeaturedPostsFeed(), name='featured'),
389
path('category/<slug:category_slug>/', CategoryFeed(), name='category'),
390
]
391
392
# Access in templates:
393
# {% url 'blog_feeds:latest' %}
394
# {% url 'blog_feeds:featured' %}
395
# {% url 'blog_feeds:category' category.slug %}
396
```