I've got a project running Django CMS and django-mobile for rendering different templates to mobile defines.
With page caching enabled in Django CMS it's possible to see the full mobile template displayed on a desktop browser or the other way around; desktop on mobile.
From some Google docs, I believed the resolution to this was setting middleware for patch_vary_headers;
from django.utils.cache import patch_vary_headers
class VaryHeaderMiddleware(object):
def process_response(self, request, response):
# Set Vary Header based on
# https://developers.google.com/webmasters/smartphone-sites/details
patch_vary_headers(response, ['User-Agent'])
return response
With the CMS_PAGE_CACHE disabled I've not seen full page templates rendered to the wrong devices, but I have got a page which as rendered with the desktop template, but then the apps rendered to the page through CMS placeholders have rendered their mobile template to the desktop. And this is while CMS_PLACEHOLDER_CACHE and CMS_PLUGIN_CACHE are still enabled.
Now I've just found this bug report from Django that suggests it's possible to omit the vary header when using the page caching decorator, but can this happen at a broader scale if I'm seeing mis-matched template rendering while certain elements are being cached?
I'm running the latest django-mobile 0.5.0 and I believe all middleware classes are defined in the correct order;
'project.middleware.VaryHeaderMiddleware',
'django_mobile.middleware.MobileDetectionMiddleware',
'django_mobile.middleware.SetFlavourMiddleware',
'django_mobile.cache.middleware.CacheFlavourMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
)
When the CMS_PAGE_CACHE fails to distinguish mobile from desktop devices, it's OK to switch it off and to replace it by Template fragment caching, see the docs.
The easiest way would be to start your base template with e.g.
{% load cache %}
{% cache 500 the_whole_page %}
and to end it with
{% endcache %}
I havn't tested it, but it should work.
Related
Problem description
I am starting working on a Django project and the server-side rendering template is a little hard to work with. Usually I develop the front-end application with hot module reload server so that I can see the rendered page during development.
However, for Django project I can only view the site by serving and open from browser. If I open the template directly, the include, extends are not processed, hence CSS and JavaScript are not loaded in the base template.
My question is, is there any tool or workflow that can help develop the Django template in offline so that the style and layout can be rendered properly during development?
Edit: justification
As comment mentioned there are some plugins that supports reload the Django page. However, I would like to know whether it is possible to work with the template HTML totally off the Django server, i.e. work with the html static page? There are some scenarios where I feel it is not suitable:
A page that refreshes slowly: e.g., slow database query before the page can be rendered.
A template that is not accessible normally: e.g., a part of html inside {% if %} that is not normally accessible, such as an error message.
A template that is not yet registered in the urlpatterns routes.
Thank you
I am planning on creating a single page with toolbar on the top.
I want to click on different buttons on the toolbar and get the form without a page refresh.
Is there a way I can do it with Django templates using if conditions (such as below)? And is the page refresh necessary?
{% if new_button_pressed %}
{% else %}
views.py
if request.POST.get('new'):
logger.info('user clicked new')
elif request.POST.get('last'):
logger.info('user clicked due next')
elif request.POST.get('previous'):
logger.info('user clicked due next')
Is it doable or not?
Django is a (server) backend framework. Which means that it generates the code for the the client to process. You cannot edit the contents without it reloading the page. So.. what you have in your view is not going to work just like that.
What you will need is Javascript. AJAX (if you want to do a request to the server without reloading) or jQuery if you have already rendered everything and just want to show it.
You might want to use a Javascript framework like VueJS, ReactJS or AngularJS.
An example is right here: https://realpython.com/blog/python/django-and-ajax-form-submissions/
I have a Django CMS 2.4 website and currently when detecting mobile user agent I switch to a different URL settings and serving different pages for mobile. Now I would like to use same content for both but to use different template for mobile and desktop versions so I don't need to do edits in two places and so the URL will stay the same for both. I know it would be easy to do in Django, but having Django CMS I have no control over rendering and template selection. Can I do it in any way, or should I look for a different solution?
Thank you.
Django CMS will check if there is an template variable in POST or GET in request, and if it's a valid template (it's set up in CMS_TEMPLATES in options.py), it will be used to display page.
The following snippet can be used in middleware.py for switching templates:
if request.COOKIES.get("mobi")=='y':
if request.current_page:
request.POST._mutable = True
request.POST['template'] = 'mobile/' + get_template_from_request(request)
request.POST._mutable = False
One thing you need to remember, this will only switch templates for page, to change a template for plugin you need to modify instance.template variable in render method of plugin.
I am using Memcached (with python-memcached binding) with one of my django projects. The scenario is that on the homepage i have:
A Top Bar : (This contains the links to login / User name with a link to the profile)
A Search Form
Few Blocks Of Results
Currently, I am using the cache_page() decorator to cache the whole page as follows:
#cache_page(3600)
def home(request):
# View Code Goes Here
and the above is working as expected. But as the homepage is a publicly accessible page i am facing a problem with one scenario where:
An anonymous user request the home page(the page get's cached if it
is not already).
Now the user logs in and is redirected to the homepage.
The cached homepage loads (Topbar still shows a login link instead of the logged in user's Name and profile link as the page was cached before the user logged in.)
Question:
Is there a way either on template level or on view level, that lets us specify a block we DO NOT want to cache while using cache_page() decorator ?
Please Note: I am aware that we can use {% cache %} template tag or cache.set for each block in the above scenario. But i am specifically looking for a solution where we can use the cache_page() decorator and still be able to specify a block that i do not want cached in a particular view or a template
use CACHE_MIDDLEWARE_ANONYMOUS_ONLY
yet it sounds as a middleware option, it affects #cache_page as well
I have a blog written in Django, and I started using the basic Django caching middleware with the file system caching backend. Unfortunately, this led to two things being cached that shouldn't have been: admin links (e.g. "Edit this post") for logged-in users and
prepopulated comment forms based on cookies.
To get around that, I started using the template cache tags:
{% load cache %}
...admin links...
{% cache 500 blog_entry entry.id %}
...entry...
{% endcache %}
...comment form...
But it seemed that the whole page was still getting cached as well. How do you set up the caching system to only cache the parts of the template you explicitly set?
Edit: For the comments, if someone comments on the blog, I store their name, website, and email address in the session variables. If they come back to the site, then I prepopulate those parts of the form with that data. But that means it is possible for the caching system to cache a view with prepopulated data, which is not good.
You need to remove the caching middleware now that you are caching template fragments instead of entire pages.
Add this to your settings.py:
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
This should fix the issue with admin links, I don't quite understand what your second issue (prepopulated comments) is?