Django Development Requirements

AWX Codebase Best Practices

Version:

1.0

Date:

September 2025

Based on:

AWX Enterprise Django Application Analysis

Generated by:

Claude Code AI



1. Project Structure

1.1 Modular Application Architecture

REQUIRED: Organize Django project with clear separation of concerns:

awx/
├── __init__.py              # Version management and environment detection
├── main/                    # Core business logic and models
├── api/                     # REST API layer (Django REST Framework)
├── ui/                      # Frontend integration
├── conf/                    # Configuration management
├── settings/                # Environment-specific settings
├── templates/               # Django templates
└── static/                  # Static assets

Requirements:

  • Each functional area must have its own Django app

  • Use descriptive app names that reflect business domains

  • Separate API logic from core business logic

1.2 Pre-Management Command Code

This section describes the code that runs before every management command.

AWX persistent services (i.e. wsrelay, heartbeat, dispatcher) all have management commands as entry points. So if you want to write a new persistent service, make a management command.

System jobs are implemented as management commands too.

REQUIRED: Implement custom Django management integration:

# awx/__init__.py
def manage():
    """Custom management function with environment preparation"""
    prepare_env()
    from django.core.management import execute_from_command_line

    # Version validation for production
    if not MODE == 'development':
        validate_production_requirements()

    execute_from_command_line(sys.argv)

Requirements:

  • Environment detection (development/production modes)

  • Production deployment validation

  • Custom version checking mechanisms

  • Database version compatibility checks


2. Settings Management

2.1 Environment-Based Settings Architecture

REQUIRED: Use django-split-settings for modular configuration:

# settings/defaults.py - Base configuration
# settings/development.py - Development overrides
# settings/production.py - Production security settings
# settings/testing.py - Test-specific configuration

Settings Pattern:

# development.py
from .defaults import *
from split_settings.tools import optional, include

DEBUG = True
ALLOWED_HOSTS = ['*']

# Include optional local settings
include(optional('local_settings.py'))

2.2 Sourcing config from files

REQUIRED: Sourcing config from multiple files (in a directory) on disk:

# External settings loading
EXTERNAL_SETTINGS = os.environ.get('AWX_SETTINGS_FILE')
if EXTERNAL_SETTINGS:
    include(EXTERNAL_SETTINGS, scope=locals())

3. URL Patterns and Routing

3.1 Modular URL Architecture

REQUIRED: Implement hierarchical URL organization with namespacing:

# urls.py
def get_urlpatterns(prefix=None):
    """Dynamic URL pattern generation with prefix support"""
    if not prefix:
        prefix = '/'
    else:
        prefix = f'/{prefix}/'

    return [
        path(f'api{prefix}', include('awx.api.urls', namespace='api')),
        path(f'ui{prefix}', include('awx.ui.urls', namespace='ui')),
    ]

urlpatterns = get_urlpatterns()

3.2 Environment-Specific URL Inclusion

REQUIRED: Conditional URL patterns based on environment:

This example allows the Django debug toolbar to work.

# Development-only URLs
if settings.DEBUG:
    try:
        import debug_toolbar
        urlpatterns += [path('__debug__/', include(debug_toolbar.urls))]
    except ImportError:
        pass

OPTIONAL: If you want to include your own debug logic and endpoints:

if MODE == 'development':
    # Only include these if we are in the development environment
    from awx.api.swagger import schema_view

    from awx.api.urls.debug import urls as debug_urls

    urlpatterns += [re_path(r'^debug/', include(debug_urls))]
    urlpatterns += [
        re_path(r'^swagger(?P<format>\.json|\.yaml)/$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
        re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
        re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
    ]

Requirements:

  • Use Django’s include() for modular organization

  • Implement URL namespacing for API versioning

  • Support dynamic URL prefix configuration

  • Separate URL patterns by functional area


4. Model Design

4.1 Abstract Base Models

REQUIRED: Use abstract base models for common functionality:

# models/base.py
class BaseModel(models.Model):
    """Common fields and methods for all models"""
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

class AuditableModel(BaseModel):
    """Models requiring audit trail"""
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        abstract = True

4.2 Mixin-Based Architecture

REQUIRED: Implement reusable model behaviors through mixins:

# models/mixins.py
class ResourceMixin(models.Model):
    """Common resource management functionality"""
    class Meta:
        abstract = True

class ExecutionEnvironmentMixin(models.Model):
    """Execution environment configuration"""
    class Meta:
        abstract = True

4.3 Model Organization

REQUIRED: Organize models by domain functionality:

models/
├── __init__.py
├── base.py           # Abstract base models
├── mixins.py         # Reusable model behaviors
├── inventory.py      # Inventory-related models
├── jobs.py           # Job execution models
├── credential.py     # Credential management
└── organization.py   # Organization models

Requirements:

  • One file per logical domain until the domain gets too big, create a folder for it instead. In the past, credentials were broken out into logical domains until they were moved out of AWX, then they were collapsed back down to a single file.

  • Use consistent naming conventions

  • Implement comprehensive model validation

  • Custom managers for complex queries


5. REST API Development

5.1 Custom Authentication Classes

The recommended best practice is to log all of the terminal (return) paths of authentication, not just the successful ones.

REQUIRED: Implement domain-specific authentication with logging:

# api/authentication.py
class LoggedBasicAuthentication(authentication.BasicAuthentication):
    """Basic authentication with request logging"""

    def authenticate(self, request):
        if not settings.AUTH_BASIC_ENABLED:
            return

        ret = super().authenticate(request)
        if ret:
            username = ret[0].username if ret[0] else '<none>'
            logger.info(
                f"User {username} performed {request.method} "
                f"to {request.path} through the API"
            )
        return ret

5.2 Custom Permission Classes

REQUIRED: Implement comprehensive permission checking:

# api/permissions.py
class ModelAccessPermission(permissions.BasePermission):
    """Model-based access control with hierarchy support"""

    def has_permission(self, request, view):
        if hasattr(view, 'parent_model'):
            parent_obj = view.get_parent_object()
            return check_user_access(
                request.user,
                view.parent_model,
                'read',
                parent_obj
            )
        return True

Requirements:

  • Multiple authentication methods (JWT, Session, Basic)

  • Custom pagination, renderers, and metadata classes

  • Comprehensive API exception handling

  • Resource-based URL organization

  • Logging for authentication events


6. Security Requirements

6.1 Production Security Settings

REQUIRED: Enforce secure defaults for production:

# settings/production.py
DEBUG = False
SECRET_KEY = None  # Force explicit configuration
ALLOWED_HOSTS = []  # Must be explicitly set

# Session security
SESSION_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_AGE = 1800

# CSRF protection
CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
CSRF_TRUSTED_ORIGINS = []

6.2 Django SECRET_KEY loading

REQUIRED: Implement Django SECRET_KEY loading:

# Secret key from external file
SECRET_KEY_FILE = os.environ.get('SECRET_KEY_FILE', '/etc/awx/SECRET_KEY')
if os.path.exists(SECRET_KEY_FILE):
    with open(SECRET_KEY_FILE, 'rb') as f:
        SECRET_KEY = f.read().strip().decode()
else:
    if not DEBUG:
        raise ImproperlyConfigured("SECRET_KEY must be configured in production")

For more detail, refer to the Django documentation.

6.3 Proxy and Network Security

REQUIRED: Configure reverse proxy security:

# Proxy configuration
REMOTE_HOST_HEADERS = ['REMOTE_ADDR', 'REMOTE_HOST']
PROXY_IP_ALLOWED_LIST = []
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

Requirements:

  • External secret file management

  • Secure cookie configuration

  • CSRF protection with trusted origins

  • Proxy header validation

  • Force HTTPS in production


7. Database Management

7.1 Advanced Database Configuration

REQUIRED: Robust database connections for production:

# Database configuration with connection tuning
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DATABASE_NAME', 'awx'),
        'ATOMIC_REQUESTS': True,
        'CONN_MAX_AGE': 0,
        'OPTIONS': {
            'keepalives': 1,
            'keepalives_idle': 5,
            'keepalives_interval': 5,
            'keepalives_count': 5,
        },
    }
}

7.2 Database Version Validation

REQUIRED: Implement database compatibility checking:

# PostgreSQL version enforcement
def validate_database_version():
    from django.db import connection
    if (connection.pg_version // 10000) < 12:
        raise ImproperlyConfigured(
            "PostgreSQL version 12 or higher is required"
        )

7.3 Migration Management

REQUIRED: Structured migration organization

migrations/
├── 0001_initial.py
├── 0002_squashed_v300_release.py
├── 0003_squashed_v300_v303_updates.py
└── _migration_utils.py

Requirements: It is best practice to not to re-write migrations. If possible, include a reverse migration, especially for data migrations to make testing easier.


8. Testing Standards

8.1 Pytest Configuration

REQUIRED: Comprehensive test setup with optimization:

# pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = awx.main.tests.settings_for_test
python_files = *.py
addopts = --reuse-db --nomigrations --tb=native
markers =
    ac: access control test
    survey: tests related to survey feature
    inventory_import: tests of code used by inventory import command
    integration: integration tests requiring external services

8.2 Test Settings Module

REQUIRED: Dedicated test configuration:

# settings/testing.py
from .defaults import *

# Fast test database
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
DATABASES['default']['NAME'] = ':memory:'

# Disable migrations for speed
class DisableMigrations:
    def __contains__(self, item):
        return True
    def __getitem__(self, item):
        return None

MIGRATION_MODULES = DisableMigrations()

8.3 Coverage Requirements

REQUIRED: Enforce comprehensive test coverage:

# Coverage targets
COVERAGE_TARGETS = {
    'project_overall': 75,
    'library_code': 75,
    'test_code': 95,
    'new_patches': 100,
    'type_checking': 100,
}

Requirements:

  • Database reuse for faster execution

  • Skip migrations in tests

  • Custom test markers for categorization

  • Dedicated test settings module

  • Comprehensive warning filters


9. Application Configuration

9.1 Advanced AppConfig Implementation

REQUIRED: Custom application configuration with initialization:

# apps.py
class MainConfig(AppConfig):
    name = 'awx.main'
    verbose_name = _('Main')
    default_auto_field = 'django.db.models.AutoField'

    def ready(self):
        super().ready()

        # Feature loading with environment checks
        if not os.environ.get('AWX_SKIP_FEATURES', None):
            self.load_credential_types()
            self.load_inventory_plugins()
            self.load_named_urls()

        # Signal registration
        self.register_signals()

    def load_credential_types(self):
        """Load credential type definitions"""
        pass

    def register_signals(self):
        """Register Django signals"""
        pass

Requirements:

  • Custom AppConfig for complex initialization

  • Feature loading in ready() method

  • Environment-based feature toggling

  • Plugin system integration

  • Signal registration


10. Middleware Implementation

10.1 Custom Middleware for Enterprise Features

REQUIRED: Implement domain-specific middleware:

# middleware.py
class SettingsCacheMiddleware(MiddlewareMixin):
    """Clear settings cache on each request"""

    def process_request(self, request):
        from django.conf import settings
        if hasattr(settings, '_awx_conf_memoizedcache'):
            settings._awx_conf_memoizedcache.clear()

class TimingMiddleware(threading.local, MiddlewareMixin):
    """Request timing and performance monitoring"""

    def process_request(self, request):
        self.start_time = time.time()

    def process_response(self, request, response):
        if hasattr(self, 'start_time'):
            duration = time.time() - self.start_time
            response['X-Response-Time'] = f"{duration:.3f}s"
        return response

Requirements:

  • Settings cache management middleware

  • Performance monitoring middleware

  • Thread-local storage for request data

  • Conditional middleware activation


11. Deployment Patterns

11.1 Production-Ready ASGI/WSGI Configuration

REQUIRED: Proper application server setup:

# asgi.py
import os
import django
from channels.routing import get_default_application
from awx import prepare_env

prepare_env()
django.setup()

application = get_default_application()

# wsgi.py
import os
from django.core.wsgi import get_wsgi_application
from awx import prepare_env

prepare_env()
application = get_wsgi_application()

Compliance Checklist

Development Standards

Requirement

Status

Modular app architecture implemented

Environment-based settings configured

Custom authentication and permissions

Comprehensive test coverage (>75%)

Security settings enforced

Database optimization configured

Static files properly organized

Custom middleware implemented

Production Readiness

Requirement

Status

External secret management

Database version validation

Version deployment verification

Performance monitoring

Security headers configured

HTTPS enforcement

Proper logging setup

Error handling and monitoring

Code Quality

Requirement

Status

Abstract base models used

Mixin-based architecture

Custom management commands

Plugin system support

Signal registration

Migration organization

API documentation

Type hints and validation


References


Document Maintainer: Development Team
Last Updated: September 2025
Review Schedule: Quarterly