Django - how to cache template for all url prefix - django

I have a Django app which renders html template and loads data into html via ajax from front end(based on url's dynamic id).
For eg., this is my site's dynamic url pattern "www.mysite.com/order/< some dynamic id>", I want django to cache & return all the requests to this url prefix r"^**www.mysite.com/order/**" to render the html without hitting my views function.
Currently, each dynamic id in the url pattern ("/order/100","/order/101","/order/102..etc")is coming to my views and rendering the same template for each.
I'm expecting, anyone visits with prefix "/order/" the html template needs to be rendered automatically without hitting my views. I'm currently using redislite for caching, Please help me with a solution.
UPDATE : It seems using a front-end framework like React or Angular JS will solve my "avoiding html template rendering" case with django. I didn't wanted django to waste time on rendering html, so I thought of caching the templates.

You can cache per-view using cache_page. This may be most appropriate for what you're trying to do.
from django.views.decorators.cache import cache_page
#cache_page(60 * 15) # 15 mins
def my_view(request):
...
Or you can cache fragments of templates, where you use the cache template tag and a time (in seconds) to cache the block of markup;
{% load cache %}
{% cache 500 sidebar %}
.. sidebar ..
{% endcache %}
This type of caching can be as simple as above, or you can do more complex caching by varying on the logged in user, for example. You can read the docs on that here

Related

What are the best ways to make your website faster such that it loads up faster and consumes less data in django

Currently I am working on a django website. I had two queries about speeding up my website.
I have a products page in which I display products. Currently when I tested it with 15 pics each sizing around 8-10mb the page took too much time to load. What should be the appropriate size of the image such that it follows the above conditions and also the image quality does not get very bad.
2)I am having a page where all the products are displayed of all categories and its view look like below
qs = Product.objects.select_related('category').order_by(*sorting)
types = [
(k, list(vs))
for k, vs in groupby(qs, attrgetter('category'))
]
I wanted to know will having different pages for different categories will help to load the site faster by filtering the products such as p=Product.objects.filter() . Or filtering would take the same time as to show all products in one single page?
1.1) To reduce image size, I highly recommend you to use django-imagekit which is the perfect tool to resize images on Django
1.2) Make sure your images are loaded with apporpriate caching headers (expires and CacheControl)
2.1) For your query, you can make the query from the Category model to avoid manually grouping your results:
# this retrieve categories and associated products
categories = Category.objects.all().prefetch_related('product_set')
And in your template :
{% for category in categories %}
{{ category.name }}
{% for product in category.product_set.all %}
{{ product.name }}
{% endfor %}
{% endfor %}
2.2) You can make use of the cache_page decorator to save your page in cache :
from django.views.decorators.cache import cache_page
#cache_page(60 * 15)
def my_view(request):
2.3) Do not load all of your products (if there is a lot) at once. Use a pagination strategy or an infinite scroll strategy (with ajax)
I wanted to know will having different pages for different categories will help to load the site faster by filtering the products such as p=Product.objects.filter(). Or filtering would take the same time as to show all products in one single page?
Filtering will be normally be faster, and definitely on a field with an index, and a ForeignKey has an index.
If you thus now the id of the Category, you can simply filter with:
Product.objects.filter(category_id=id_of_category)
This will filter at the database side, which will thus result in fewer records being returned to the Django/Python layer, less processing, and less rendering.

I need to cache a TemplateView with a querystring - how?

Basically, I'm trying to cache a simple search results page (generated with a TemplateView view) with a URL pattern of:
/search/?q=foo
I've tried:
#cache_page - doesn't work with querystrings (why? the stated reason "querystrings usually do not affect the results" completely depends on 'usually' meaning 'always' which is demonstrably false);
django-fancy-cache - doesn't work with CBVs (but in principle appears to do exactly what I want);
Adjusting the action on my form with an onSubmit() to change the url pattern (so that there's no querystring) - for SOME reason this messes up every other page on the site even though the test form doesn't exist on any of those pages.
I can't be the first person in the universe who needs this :-) ... Pointers to something I've missed in the Django docs or to a package that has eluded my search for it GREATLY appreciated.
You could use template fragment caching for that purpose, using the query string to uniquely identify the cache fragment. In your template:
{% load cache %}
{% cache 3600 search_results request.META.QUERY_STRING %}
<!-- search results here -->
{% endcache %}

Django CMS - Call a cmsplugin in a template tag

My problem
With Django CMS 2.3.3, when creating a Page I use cmsplugin_picture* next to a couple of other cmsplugins. In my cms template, instead of doing:
{% placholder "content" %} //calling the Django Page including all plugins...
I would like to call each cmsplugin seperately, but how would I do that?
I looked at Django tag template (filters) here and also studied Django CMS template tags here, but neither seem to suggest that possibility. I have to say I am a beginner so I might not have connected the dots...
What I try to achieve:
In my template I have a IMG tag (outside of the {% placeholder "content" %} tag) which I want to populate with an image url that I define in my Page/cmsplugin_picture. So I am looking for a placeholder tag that allows me to grab that image. In my wildest dreams I would name it:
{% show_placeholder "content" request.current_page.get_cmsplugin_picture %}
Obviously the above doesn't work, but does something like this exist?
**I have also tried cmsplugin_filer, but to me it isn't necessarely more beneficial to fix this particular problem.*
EDIT:
What I mean by Page/cmsplugin_picture -> In a Django CMS Page you can select between your installed cmsplugins to add to a Page. In my case I select cmsplugin_picture and upload an image (within that plugin). This image I want to 'call' in my Django Template. So it is a not a static url, but dynamic.
You should make a second placeholder where your img tag is (and optionally limit the types and amount of plugins using CMS_PLACEHOLDER_CONF (http://docs.django-cms.org/en/2.3.3/getting_started/configuration.html#cms-placeholder-conf).

New url syntax from django 1.3/dev onwards

Why did the django core developers allow the url templatetag to point directly to a django view function? (reference - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#url)
{% load url from future %}
{# 1st method: pointing to a view function #}
{% url 'app_views.client' %}
{# 2nd method: pointing to a named url #}
{% url 'myapp:view-name' %}
One can already name the url in urls.py and hence use the 2nd method to point to a specific url. It doesn't feel right to allow developers to actually reference a view function directly from the template.
Does anyone know why this decision was made?
Passing a dotted view function name to the {% url %} template tag is simply the form the template tag took in the earlier days of Django, before you could name URLs. It's still supported, though as you point out, you probably wouldn't use it in a modern application.
URLs in Django are just mappings to views. Therefore, in the template, using a named URL is just indirectly referencing the view anyway.
The exception is where a single view is mapped to by multiple URLs.
Also note that they are planning to change the syntax of the url tag in 1.5. It will take a context variable as the parameter, rather than a string. It will still take views or named URLs though.

Django - Pre render signal?

I have a 'live settings' app which I use to store certain global site settings. Certain pages of my site reference these settings, although generally they only use 2-3 at a time. I access these settings using a custom template tag like so:
{% settings site_name %}
Each time I use this tag, the model will retrieve the setting from the database, so if I had something like:
{% settings site_name %} {% settings num_articles %}
the database would get queried twice.
What I'd like to do is not hit the database more than once per page for the settings values, if I could get all the settings used on a page and then hit the database to retrieve them all, that would be much better.
I had a look through the documentation and it seems Django has no pre render signal which I could use to update any references to the settings, so does anyone have any suggestions how I could optimise this system? And yes obviously caching is the obvious answer but I'd still like to improve on this for when the page isn't cached.
Agreeing with Daniel that process_template_response is the hook you're looking for. I don't know how many settings you have, but it could also make sense to retrieve all settings once, and store them in some dictionary like structure, so you can access them anytime without hitting the database. You could retrieve them once either per request, or - even if your settings do barely change - when django initializes. You could additionally use django's signals to update your cached settings on delete or update.
If you have a look at django-dbsettings you will see it does a similar thing!
Django 1.3 includes the new TemplateResponse class, which allows you to modify the response later in the rendering process - eg in middleware. This looks like it might do what you want.
If you wish to stick to a scheme similar to what you already have, I'd implement a filter that takes in a list of keys and returns a dict with all the relevant values.
Example filter:
def get_settings(key_list):
# take values from conf.settings. In practice, can be from any source
return dict((k, getattr(settings, k, None)) for k in key_list.split(","))
register.filter("get_settings", get_settings)
Usage:
{# load multiple values with a single call #}
{% with "KEY1,KEY2"|get_settings as settings %}
setting values {{ settings.KEY1 }} and {{ settings.KEY2 }}
{% endwith %}
Note that I used a filter instead of a tag because the with builtin expects a single value before as.