reading and caching html fragment for use on django template - django

I need to grab four html fragments from an external web site and display them within my django site's header and footer. I definitely need to cache these for some period of time.
My initial thought was to use urllib2 to read the http and then write the html to files to my server. Implemented through a Django context processor, the code checks the timestamps of the four files and retrieves updated versions if necessary before reading them into template variables.
I appear to be maxing out Django's template variable size for one of the four files. This forced me to use readlines() and to pass that file into the template as an array.
Is there a more elegant way to retrieve four html fragments from an external site, cache them and pass them to my templates?
Here's what my base.html template looks like now:
{{ integration_prehead|safe }}
<head>
{{integration_head|safe }}
...
</head>
{% for l in integration_topper %}{{ l|safe }}{% endfor %}
{{ block content }}{{ endblock content }}
{{ integration_footer|safe }}
The prehead.html isn't much of anything other than the doctype and opening html tag. The head.html is a bunch of javascript and stylesheets. The topper.html and the footer.html are the biggest pieces and they're the top and bottom of the pages. The topper, in particular, can change every 15 minutes so it's not practical to hard-code it on my templates.
Topper is 39k and too big to read into a single Django template variable, hence the for loop.

If you have any control over the server you're pulling the fragments from, your best bet is to set up dedicated views that return just the fragments and not the entire HTML document.
You can then use Django views to either manually save the fragments to disk or use Django's Cache framework. The cache framework will be much more robust and provide additional means of storage such as via database or memcached, but it's not guaranteed to store the fragment for a defined period of time. For example, memcached will lose everything if the server has to be restarted.
If the source server is not in your control, I'd highly recommend that you run the document through an HTML parser first, and pull out and pass in to your template only the pieces that your need. BeautifulSoup is a nice one for python.

Related

Django additional arguments to per view cache

In the excellent Django cache framework documentation it mentions the possibility of adding additional arguments to template fragment caching:
Sometimes you might want to cache multiple copies of a fragment
depending on some dynamic data that appears inside the fragment. For
example, you might want a separate cached copy of the sidebar used in
the previous example for every user of your site. Do this by passing
additional arguments to the {% cache %} template tag to uniquely
identify the cache fragment:
{% load cache %} {% cache 500 sidebar request.user.username %}
.. sidebar for logged in user .. {% endcache %}
It’s perfectly fine to specify more than one argument to identify the fragment.
Simply pass as many arguments to {% cache %} as you need.
However it doesn't seem to mention anything about doing something similar when the per-view cache. It mentions the possible to use #vary_on_headers and #vary_on_cookie, but that is not quite the same. In my use case I would for example like to use something like request.user.company to ensure all users from the same company get the same cached version of a view.
Is it not possible to add such arguments to the per-view cache instead of defining it in the template?

Return html file without rendering in django

I want to use Django with single-page js framework and Django variable braces {{ clashes with framework delimiters. So I need to return some html file like response in my view without rendering file with any context.
I've seen that many developers make reconfiguration of delimiters in JS but may be there are more suitable approach to save Django routing?
Put the desired code between {% verbatim %} and {% endverbatim %}. This will prevent Django from rendering it. You can read more in official documentation.
It is much better to remove template rendering from this altogether. From the point of view of Django, your JS framework's templates are static files, and they should be served as such.

Combining Django Templates and Polymer

I've been stuck for the past few hours trying to figure out why the core Polymer elements are not being displayed properly in a Django application I'm making to act as a personal webpage. The application at the moment just points to an index.html page which, if you follow the tutorial on Polymer, is up to step one.
However, the components are not loading on my page. The static files are all set up correctly, and there's subtle animation from the css files being loaded correctly, but the Roboto font and the core-elements are not being displayed. Running the site as a normal HTML file does everything correctly.
Is there a specific way to user Polymer in a Django template?
Thanks.
See Eric's answer to this on the polymer-dev mailing list: https://groups.google.com/forum/?fromgroups=#!searchin/polymer-dev/django/polymer-dev/N2R8qknalOI/58ZhC1gWFh4J
Relevant excerpt:
Django 1.5 has support for the verbatim tag. You can wrap your inlined element definitions in that:
https://docs.djangoproject.com/en/1.5/ref/templates/builtins/#verbatim
Example code snippet:
{% verbatim %}
<template repeat="{{item as items}}">
<my-element name="{{item.name}}"></my-element>
</template>
{% endverbatim %}
<script>
document.querySelector("template').model = {{items}}; // items here is filled by the server's template.
</script>
I'm pretty sure this has to do with the fact that Django uses the same {{}} in its templates as Polymer.
I'm adding this answer as a compliment to the already accepted answer.
You can force django to require a space for it's template tags. So for any django template tags you have to use {{ variable }} and for polymer you will use {{variable}}.
Here is a very simple module/app I created to "prepare" django for use alongside polymer.
https://github.com/andrewebdev/django-ostinato/blob/2c435dea23319be6e9011e7381afca2b4092b5a2/ostinato/polyprep/init.py
Credit goes to https://github.com/nebrybledu for this suggestion.

Isn't it rough to retrieve flatpages via get_flatpages template tag from its url instead of a page identifier?

As you can read on the django reference or hacking a bit, get_flatpages can be used as follow:
{% get_flatpages as flatpages %}
{% get_flatpages for someuser as flatpages %}
{% get_flatpages '/about/' as about_pages %}
{% get_flatpages prefix as about_pages %}
{% get_flatpages '/about/' for someuser as about_pages %}
So, if I want to get a specific page I need to do it via its url or a prefix, which is somewhat rough, because my template code become data dependant, I meant, if I change the url of certain flat page then it is necessary to change my template code too.
A more flexible idea would be including an identifier to each page, addable through e.g. the 'Advanced options' section, so that the page can be refered via its identifier, thus we could do something like this:
{% get_flatpages 'about' as about_pages %}
Which is more flexible and less data dependant, no matter what url the page has, note we could change the page's url without changing the template code.
Is there something like that in the framework?, of course I could customize this app or to use a third-party app, but this isn't the point ;-)
Have you any other idea to deal with?
No, I don't believe there's any support for what you're asking for in Django at present. The docs you linked to for flatpages say:
A flatpage is a simple object with a URL, title and content. Use it for one-off, special-case pages, such as “About” or “Privacy Policy” pages, that you want to store in a database but for which you don’t want to develop a custom Django application.
My reading of this is "this is the bare minimum we're providing, and if you want any more you'll have to code it yourself". I agree that your proposal of allowing pages to be referred to by a symbolic name (which perhaps defaults to their URL) is more flexible, but you're probably better off raising an issue for it or discussing on the mailing list than hoping a dev happens upon your question on StackOverflow.
In the short term, you could look at some of the pre-built CMS-like Django apps. Django-page-cms is relatively lightweight (it's a relatively small app itself but does have a bunch of dependencies) and you could accomplish what you're after: each page is referred to by its slug (aka url / name), but you can define aliases / redirects to given pages for arbitrary URLs.

How to manage Javascript modules in django templates?

Lets say we want a library of javascript-based pieces of functionality (I'm thinking jquery):
For example:
an ajax dialog
a date picker
a form validator
a sliding menu bar
an accordian thingy
There are four pieces of code for each: some Python, CSS, JS, & HTML.
What is the best way to arrange all these pieces so that:
each javascript 'module' can be neatly reused by different views
the four bits of code that make up the completed function stay together
the css/js/html parts appear in their correct places in the response
common dependencies between modules are not repeated (eg: a javascript file in common)
x--------------
It would be nice if, or is there some way to ensure that, when called from a templatetag, the templates respected the {% block %} directives. Thus one could create a single template with a block each for CSS, HTML, and JS, in a single file. Invoke that via a templatetag which is called from the template of whichever view wants it. That make any sense. Can that be done some way already? My templatetag templates seem to ignore the {% block %} directives.
x--------------
There's some very relevant gasbagging about putting such media in forms here http://docs.djangoproject.com/en/dev/topics/forms/media/ which probably apply to the form validator and date picker examples.
Been a while since I posted this problem. What I've been doing to solve it is:
write the javascript parts you need as a library which is served statically
call the routines in the static library from the template with your server side values
Restraint is required to write it in such a way that it acts as a client side script only; don't be tempted to try and inject values from the server at the time of serving the js. Ultimately I've found it less confusing to apply server side variables strictly in the html template.
In this way I'm able to:
keep the javascript selectors on html tags inside the same file (ie: the template)
avoid templatetags altogether
re-use each javascript library in different places, and
keep the css/js/html pieces in all the places where they're expected to be found
It's not perfect, but it's getting me by till a neater idea comes along.
For example a js library in "media/js/alertlib.js" might include:
function click_alert(selector, msg){
$(selector).click(function(){ alert(msg) })
}
and the template has:
<script type="text/javascript" src="media/js/alertlib.js"></script>
<script type="text/javascript">
click_alert('#clickme', {% message %})
</script>
<div id='clickme'>Click Me</div>
If more than one page uses a given JS file you should consider concatenating all of them together and minifying the result. This reduces net connects which will improve overall page load time. Don't forget to bump your expire time out to at least a week or two.
Have a look at Django Sekizai that has been created for just that purpose.
I think you are going to have a hard time keeping all four pieces together and applying them in a fell swoop - simply because some appear in your <head> tags and others in the <body> tags.
What have done is made sure that jQuery is loaded for all pages on my base.html (as well as my base css file) ... then, I have block tags for {% block css %} and {% block js %}. Templates that inherit the base.html file can supply their own javascript and css (and only the stuff that is needed).
I have created some template tags that create ajax functions whose output is based on the object being displayed (for example, including the object_id) -- which cuts down on re-coding.
One thing I haven't tried but am interested in is django-compress.