django-cms中根据屏幕分辨率使用不同模板的最佳实践问询
Great question! When CSS media queries aren’t enough and you need full template swaps based on screen resolution in django CMS, here are the most reliable production-proven approaches I’ve used:
Since servers can’t natively detect a user’s screen resolution, you’ll first need to pass that data from the frontend to the backend. Here’s how to set this up:
Step 1: Frontend Resolution Capture & Cookie Storage
Add a small script to your base template to capture the screen width and store it in a cookie (so subsequent requests include this data):
document.addEventListener('DOMContentLoaded', function() { const screenWidth = window.screen.width; // Set cookie with 1-day expiration document.cookie = `screen_res=${screenWidth}; max-age=86400; path=/`; });
Step 2: Custom Middleware to Parse the Cookie
Create a middleware that reads the cookie and attaches the resolution data to the request object:
# myapp/middleware.py class ScreenResolutionMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): screen_res = request.COOKIES.get('screen_res') if screen_res: request.screen_width = int(screen_res) else: # Fallback to a default (e.g., desktop) request.screen_width = 1200 response = self.get_response(request) return response
Don’t forget to add this to your MIDDLEWARE setting in settings.py.
Step 3: Dynamic Template Loading in django CMS
You can override the template selection for CMS pages either via a custom apphook or by modifying the CMS page’s view. For example, in a custom apphook:
# myapp/cms_apps.py from django_cms.apphook_pool import apphook_pool from django_cms.app_base import CMSApp from django.views.generic import TemplateView class ResponsiveApphook(CMSApp): name = "Responsive App" urls = ["myapp.urls"] apphook_pool.register(ResponsiveApphook) # myapp/views.py class ResponsivePageView(TemplateView): def get_template_names(self): # Define your breakpoints if self.request.screen_width < 768: return ["myapp/mobile_template.html"] elif self.request.screen_width < 1024: return ["myapp/tablet_template.html"] else: return ["myapp/desktop_template.html"]
If you need the template to switch immediately when the user resizes their window (without a page reload), use client-side rendering:
Step 1: Load a Base Skeleton Template
Start with a minimal base template that only includes the necessary scripts and a placeholder for content:
<!-- base_skeleton.html --> <!DOCTYPE html> <html> <head> <title>{% block title %}{% endblock %}</title> <script src="{% static 'js/responsive_switcher.js' %}"></script> </head> <body> <div id="content-container"></div> </body> </html>
Step 2: Async Template Loading Script
Create a script that checks the window size, fetches the appropriate template via an API endpoint, and replaces the content container:
// static/js/responsive_switcher.js function loadTemplate(width) { let templateUrl; if (width < 768) { templateUrl = '/api/templates/mobile/'; } else if (width < 1024) { templateUrl = '/api/templates/tablet/'; } else { templateUrl = '/api/templates/desktop/'; } fetch(templateUrl) .then(response => response.text()) .then(html => { document.getElementById('content-container').innerHTML = html; }); } // Initial load loadTemplate(window.screen.width); // Listen for window resizing (debounce to avoid excessive requests) let resizeTimeout; window.addEventListener('resize', function() { clearTimeout(resizeTimeout); resizeTimeout = setTimeout(() => loadTemplate(window.innerWidth), 200); });
Step 3: Create the API Endpoint
Add a view that returns the rendered template based on the request (you can reuse the screen width detection from the middleware here):
# myapp/views.py from django.http import HttpResponse from django.template.loader import render_to_string def get_responsive_template(request): if request.screen_width < 768: html = render_to_string('myapp/mobile_template.html', request=request) elif request.screen_width < 1024: html = render_to_string('myapp/tablet_template.html', request=request) else: html = render_to_string('myapp/desktop_template.html', request=request) return HttpResponse(html, content_type='text/html')
Map this view to a URL in your urls.py.
- Caching: django CMS’s page caching will cache the first rendered template. To avoid this, add the screen resolution to your cache key. You can use a custom cache backend or modify the
CMS_CACHE_KEY_FUNCTIONsetting to includerequest.screen_width. - Fallback Behavior: Always include a default template for cases where the cookie isn’t set (e.g., first-time visitors without JavaScript).
- Performance: For client-side swapping, debounce resize events and consider caching templates locally with
localStorageto reduce API calls.
内容的提问来源于stack exchange,提问作者user3260061

