Skip to content

Django CMS Removal Guide

Version: 0.2.0
Date: January 27, 2025
Status: CMS functionality temporarily disabled for deployment simplification

Overview

This document details the systematic removal of Django CMS dependencies from the Barodybroject application. The removal was implemented using careful commenting rather than deletion, allowing for potential future restoration while immediately resolving deployment conflicts and simplifying the application architecture.

Why CMS Was Removed

Primary Motivations

  1. Deployment Simplification: CMS dependencies were causing deployment conflicts and complexity
  2. Quota Limitations: Azure App Service quotas required switching to Container Apps, which worked better with simplified architecture
  3. Development Focus: Core parody news generation functionality doesn't require full CMS capabilities
  4. Cost Optimization: Fewer dependencies mean simpler infrastructure and lower costs

Strategic Decision

The CMS removal was implemented as temporary commenting rather than permanent deletion to: - Preserve all existing CMS-related code for potential future restoration - Allow immediate deployment success while maintaining code history - Provide clear restoration path when CMS functionality is needed - Maintain git history and development context

Detailed Changes by Component

1. Django Settings (src/barodybroject/settings.py)

Changes Made:

INSTALLED_APPS = [
    # Django CMS and related apps (temporarily commented for deployment)
    # 'cms',
    # 'menus',
    # 'sekizai',
    # 'djangocms_admin_style',
    # 'djangocms_text_ckeditor',
    # 'djangocms_link',
    # 'djangocms_file',
    # 'djangocms_picture',
    # 'djangocms_video',
    # 'djangocms_googlemap',
    # 'djangocms_snippet',
    # 'djangocms_style',
    # 'djangocms_column',
    # 'filer',
    # 'easy_thumbnails',
    # 'mptt',
    # 'treebeard',
    # And 20+ more CMS-related apps...

    # Core Django apps remain active
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    # ... (standard Django apps)
    'parodynews',  # Main application
]

Middleware Changes:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    # 'cms.middleware.user.CurrentUserMiddleware',  # CMS disabled
    # 'cms.middleware.page.CurrentPageMiddleware',  # CMS disabled
    # 'cms.middleware.toolbar.ToolbarMiddleware',   # CMS disabled
    # 'cms.middleware.language.LanguageFallbackMiddleware',  # CMS disabled
    'django.middleware.common.CommonMiddleware',
    # ... (standard Django middleware)
]

Template Context Processors:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'OPTIONS': {
            'context_processors': [
                # 'cms.context_processors.cms_settings',  # CMS disabled
                # 'sekizai.context_processors.sekizai',   # CMS disabled
                'django.template.context_processors.request',
                # ... (standard Django context processors)
            ],
        },
    },
]

2. Models (src/parodynews/models.py)

CMS-Dependent Models Commented:

# CMS-related models temporarily disabled for deployment
# class Entry(CMSPlugin):
#     """CMS plugin for displaying news entries"""
#     title = models.CharField(max_length=200)
#     content = PlaceholderField('content')
#     created_at = models.DateTimeField(auto_now_add=True)
#     
#     def __str__(self):
#         return self.title

# class PostPluginModel(CMSPlugin):
#     """CMS plugin model for post integration"""
#     post = models.ForeignKey('Post', on_delete=models.CASCADE)
#     template = models.CharField(max_length=100, default='post_plugin.html')

Core Models Preserved: - Post model (main content model) - Fully functional - Category model - Fully functional
- Tag model - Fully functional - User authentication models - Fully functional

3. Admin Configuration (src/parodynews/admin.py)

CMS Admin Integration Removed:

from django.contrib import admin
from .models import Post, Category, Tag
# from cms.admin.placeholderadmin import FrontendEditableAdminMixin  # CMS disabled

# Standard Django admin (no CMS integration)
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):  # Removed FrontendEditableAdminMixin
    """Standard Django admin for Post model"""
    list_display = ['title', 'author', 'category', 'status', 'created_at']
    list_filter = ['status', 'category', 'created_at']
    search_fields = ['title', 'content']
    prepopulated_fields = {'slug': ('title',)}

    # CMS frontend editing capabilities temporarily removed
    # frontend_editable_fields = ("title", "content")

4. Views (src/parodynews/views.py)

CMS-Related Imports and Views Commented:

from django.shortcuts import render, get_object_or_404
# from cms.models import Page  # CMS disabled
# from cms.utils.page_resolver import get_page_from_request  # CMS disabled

def post_list(request):
    """Standard Django view without CMS integration"""
    posts = Post.objects.filter(status='published')
    # CMS page context removed:
    # current_page = get_page_from_request(request)
    # cms_context = {'current_page': current_page}

    context = {
        'posts': posts,
        # **cms_context,  # CMS context disabled
    }
    return render(request, 'parodynews/post_list.html', context)

5. URL Configuration (src/barodybroject/urls.py)

CMS URL Patterns Disabled:

from django.contrib import admin
from django.urls import path, include
# from cms.sitemaps import CMSSitemap  # CMS disabled
# from django.conf.urls.i18n import i18n_patterns  # CMS disabled

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('parodynews.urls')),
    # CMS URLs temporarily disabled
    # path('', include('cms.urls')),
]

# CMS i18n patterns disabled
# urlpatterns += i18n_patterns(
#     path('', include('cms.urls')),
# )

6. Templates

Base Template (src/parodynews/templates/base.html)

Before (CMS-integrated):

{% load cms_tags menu_tags sekizai_tags %}
{% load static %}
<!DOCTYPE html>
<html>
<head>
    {% render_block "css" %}
    <title>{% page_attribute "page_title" %}</title>
</head>
<body>
    {% cms_toolbar %}
    {% show_menu 0 1 100 100 "menu.html" %}

    {% block content %}
        {% placeholder "content" %}
    {% endblock %}

    {% render_block "js" %}
</body>
</html>

After (Pure Django):

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Parody News Generator{% endblock %}</title>

    <!-- Bootstrap 5.3.3 CDN -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css">

    {% block extra_css %}{% endblock %}
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">Parody News</a>
            <!-- Standard Bootstrap navigation -->
        </div>
    </nav>

    <main class="container my-4">
        {% block content %}{% endblock %}
    </main>

    <!-- Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
    {% block extra_js %}{% endblock %}
</body>
</html>

New Test Template (src/parodynews/templates/test.html)

Added for Deployment Validation:

{% extends 'base.html' %}

{% block title %}Test Page - Parody News{% endblock %}

{% block content %}
<div class="container">
    <h1>🚀 Deployment Test Page</h1>
    <div class="alert alert-success">
        <h4>✅ Application Successfully Deployed!</h4>
        <p>This test page confirms that:</p>
        <ul>
            <li>Django application is running correctly</li>
            <li>Templates are rendering properly</li>
            <li>Bootstrap 5.3.3 is loaded and functional</li>
            <li>Static files are being served</li>
        </ul>
    </div>
</div>
{% endblock %}

Impact Assessment

What's Lost (Temporarily)

  1. Content Management Interface: No web-based content editing
  2. Page Hierarchy: No CMS page tree structure
  3. Plugin System: No CMS plugins for rich content
  4. Frontend Editing: No in-place content editing
  5. Multi-language Support: CMS i18n features disabled
  6. Advanced Menus: No CMS-generated navigation menus

What's Preserved

  1. Core Functionality: All parody news generation features work
  2. Database Models: Core content models (Post, Category, Tag) fully functional
  3. User Authentication: Complete user management system
  4. Admin Interface: Django admin for content management
  5. API Endpoints: All REST API functionality intact
  6. Bootstrap UI: Modern, responsive interface with Bootstrap 5.3.3

What's Improved

  1. Deployment Speed: Faster container builds and deployments
  2. Resource Usage: Lower memory and CPU requirements
  3. Dependency Management: Fewer potential security vulnerabilities
  4. Development Velocity: Simpler debugging and development
  5. Cost Efficiency: Reduced infrastructure requirements

Restoration Guide

Quick Restoration Process

To restore CMS functionality in the future:

  1. Uncomment Settings:

    # Edit src/barodybroject/settings.py
    # Uncomment all CMS-related apps in INSTALLED_APPS
    # Uncomment CMS middleware
    # Uncomment CMS context processors
    

  2. Uncomment Models:

    # Edit src/parodynews/models.py
    # Uncomment Entry and PostPluginModel classes
    

  3. Uncomment Admin:

    # Edit src/parodynews/admin.py
    # Uncomment FrontendEditableAdminMixin import and usage
    

  4. Uncomment Views:

    # Edit src/parodynews/views.py
    # Uncomment CMS imports and context additions
    

  5. Uncomment URLs:

    # Edit src/barodybroject/urls.py
    # Uncomment CMS URL patterns and i18n patterns
    

  6. Update Templates:

    # Edit templates to re-add CMS template tags
    # Restore cms_tags, menu_tags, sekizai_tags
    # Add back placeholders and CMS-specific features
    

  7. Database Migration:

    python manage.py makemigrations
    python manage.py migrate
    

Automated Restoration Script

A future enhancement could include a restoration script:

#!/bin/bash
# cms_restore.sh - Automated CMS restoration script
# 
# This script would:
# 1. Find all commented CMS code sections
# 2. Uncomment them systematically
# 3. Run database migrations
# 4. Verify CMS functionality
# 5. Update documentation

echo "🔄 Restoring Django CMS functionality..."
# Implementation would go here

Migration Notes

Database Considerations

  • No Data Loss: All database migrations preserve existing data
  • CMS Tables: CMS-related tables remain in database but unused
  • Future Migrations: CMS restoration will require running Django CMS migrations

Development Workflow

  • Feature Development: Continue normal Django development without CMS
  • Content Management: Use Django admin for content management
  • Template Development: Build with pure Django + Bootstrap patterns

Testing Strategy

  • Existing Tests: All core functionality tests continue to pass
  • CMS Tests: CMS-related tests disabled but preserved in codebase
  • Integration Tests: Template rendering and view tests updated for non-CMS flow

Conclusion

The CMS removal was a strategic decision that enabled successful Azure Container Apps deployment while preserving the option for future CMS restoration. The systematic commenting approach ensures that:

  1. Immediate Benefits: Simplified deployment and reduced complexity
  2. Future Flexibility: Complete restoration path available
  3. Code Preservation: No loss of development effort or functionality
  4. Clear Documentation: Comprehensive guide for understanding and reversing changes

This approach demonstrates a pragmatic balance between immediate deployment needs and long-term architectural flexibility.


Related Documentation: - DEPLOYMENT-SUCCESS.md - Results of successful deployment - DEPLOYMENT-GUIDE-MINIMAL.md - Deployment instructions - CHANGELOG.md - Complete version history - README.md - Updated project overview