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

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 %}

Related

Django, Effective way to redirect URL

When a DOM change occurs, a Javascript function fires and redirect to the same website's page with certain parameters.
From the performance point of view, is the below method right?
const fire=(arg)=>{
location.href = '/admin/arg/';
}
Or should I use the {% URL 'path' %} tag ? if so, how ?
The {% url 'name' %} is obviously less efficient than calling the absolute url, but it's not going to break the bank rendering your html. What difference is it going to make? A few milliseconds?

Django - how to cache template for all url prefix

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

Make django url tag fail silently

The Django {% url %} templatetag raises a NoReverseMatch error when it can't reverse the provided URL. This is useful in development, but in production, this stops the user dead in their tracks with an ugly 500 error, blocking the whole page, and leading them to think our site is broken.
Template developers shouldn't be able to bring down the whole site with a typo. What I want to do is transparently override this behavior so that, in production only, if a reverse match can't be found, it outputs a default url, like "#", and reports the error to our exception tracking system in the background, but still lets the user continue with what they were doing without raising the 500 error.
Is there a way to replace the default {% url %} tag with my own safer version, transparently? I don't want to have to add a {% load my_custom_url_tag %} at the top of every single template on the site, because at some point people will forget, and the behavior of the tag is will otherwise be the same, the only difference is how it handles errors.
You can use the built-in url tag in silent mode, try the lookup, and then use the URL it finds—if it finds something.
From the Django docs:
This {% url ... as var %} syntax will not cause an error if the view is missing. In practice you’ll use this to link to views that are optional:
{% url 'path.to.view' as the_url %}
{% if the_url %}
Link to optional stuff
{% endif %}
Hope that helps.
By implementing your own url tag, you're opening yourself up to lots of forward compatibility issues. My recommendation would be to add custom 500 error handler instead: https://docs.djangoproject.com/en/1.4/topics/http/views/#the-500-server-error-view
I would think you would actually want the view to throw an error if a template developer has made a typo. Trying to mask that behavior seems illogical - isn't that reason enough to have some simple unit tests to make sure your views are at least returning a 200 response code?

Infinite scroll in django

Is it possible to implement facebook style loading of content while scrolling down? I would like to implement it in an ecommerce site. There are a lot of items in each category and the category page becomes too long. I could implement page numbers but my client wants me to implement that facebook type of loading. Is there anything I can use? Rest of the site has already been built.
I did look into django-endless-pagination but was not able to get it to work. Is there any demo of it so that I can look into it?
We used django endless pagination on www.mymommemories.com without too much problem. Because we were using html5media we did have to add a line to run that function with a one second delay. (setTimeOut("html5media()", 1000). Running it without the delay caused problems in some browsers. If your not using html5media, this should not be a concern however.
Core part of the template code.
{% load endless %}
{% paginate memories %}
{% for memory in memories %}
.
.
.
{% endfor %}
{% show_more %}
In the view we have the following to handle the ajax request.
if request.is_ajax():
template = page_template
return render_to_response(template,context,context_instance=RequestContext(request))
The page_template is not the whole page, just the portion related to the "paging".
I thinks the easiest way to do endless pagination is use jQuery (use $.loads).
You even don't need change the back-end code.
http://www.infinite-scroll.com/infinite-scroll-jquery-plugin/
Perhaps take a look at that?

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.