or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-forms.mdcms-integration.mdconfiguration.mdfeeds-sitemaps.mdindex.mdmodels.mdtemplates-utilities.mdviews.md

feeds-sitemaps.mddocs/

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

```