Load common content for the whole Django site - django

I want to load a list notifications for almost all the web application I am building. Should I do in every view function or View Class?

No, you should not, Django provides several mechanisms to take care of that kind of issues.
Context processors are functions that are called each time a template is rendered and which output populates that template's context. They allow you to have the same variables available everywhere in your templates.
Custom template tags and especially inclusion tags allow you to output content anywhere in a template by just calling them, which is as simple as {% my_tag_name %}.
These two mechanism coupled with template inheritance and inclusion allow you to not repeat code that is shared across many pages.

Related

Django: Built-in include tag vs custom inclusion tag

What is the difference between Django's built-in include tag and custom inclusion tags?
I have read the documentation, and both seem to to achieve the same goal: render a template passing it a context or variable.
They serve different purposes. The include tag simply includes the content from an existing template in its entirety and unmodified. A custom inclusion tag passes the context to a function which can contain logic to manipulate the context before passing it to a template.
For example, perhaps I have a panel that will be shown on multiple pages. The panel's template requires a few specific queries to be passed to it through the context. The pages that contain the panel don't require those context variables for anything else. If I include the panel template with the include tag, I would have to write those queries in every view that contains the panel and pass them as context variables.
Alternatively, I could write a custom inclusion tag that contains the queries and passes them to the panel's template. By using the custom inclusion tag I wouldn't need to repeat the code to produce its context in every view that contains the panel. My views would contain less code and would be less cluttered with context variables only used by the panel.
Although you are correct in the sense that a custom inclusion tag that simply passes on the context unmanipulated would be the same as the include tag.
Need to separate templates to smaller files? Use include tag (for readability and maintainability and DRY)
Need to include more code before rendering the template? Use inclusion tags (fetch more data, add some business logic.. it is really like another small url-less view. it is like a template function).
In principle, the point made by dgel's and YardenST's answers is correct. Additionally, a look into django's code gives a good insight on how these two options are compared in performance.
When using the default template loaders, there is absolutely no difference between the two. Both eventually make a call to the InclusionTag render() function, which in turn makes a call to template Loader get_contents() that opens the template file from filesystem. render() only caches the file in case it is used in a template for loop.
As a side note, a difference in performance would be possible by using the django.template.loaders.cached.Loader.
Last, regarding dgel's suggestion to use the inclusion tag for common context across different views: it is very much possible to avoid the small extra overhead of rendering an inclusion template, when the html markup is in a single base template that spans across many views, by using a ContextMixin. This is a quite common scenario for rendering eg. a main menu in a base template.
Just recently faced this question as I was trying to find which route is best to take - include vs inclusion tag - when there's no real extra logic that might go into an inclusion tag.
And I choose the inclusion tag for the following reasons:
more compact and readable markup in templates
<!-- include -->
{% include "path/to/funky.html" with arg1=arg1 arg2=arg2 %}
vs
<!-- inclusion tag -->
{% funky arg1 arg2 %}
easier to maintain code, if you ever had to add custom logic to the tag then it's easy to add
it enforces you to use template variables that are scoped properly, so the inclusion tag cannot inherit a variable from the parent view, makes it more resilient against weird bugs

Is it safe to render user-created Django templates?

Is it safe to let users make their own Django templates with a set of pre-defined variables, and then render this template on the server? I would only pass a very limited set of parameters to render, all of which are strings. Templates would be something like:
hey, my name is {{name}}.
So, the question is, are there any django template tags that can be abused to get information that users are not supposed to get? I'm most worried about the {% url %} tag.
P.S.
I noticed this question after filling out the title, however, my question is slightly different. I will probably allow no HTML/javascript at all, use Textile/Markdown, or find a way to restrict HTML to a very basic set of tags.
There're three main risks:
Users modifying the data. For example, rendering {{ request.user.kill }} will trigger kill() call during value lookup. To prevent this, you should set kill.alters_data = True in your model code. All built-in model methods that modify data are already marked, so the risk is only associated with your own methods or ones provided by poorly-written 3rd party apps.
Users directly accessing data they should not see. When RequestContext is used (which is most of the time), there're many variables added to template rendering context. Add user-defined templates and you're getting quite dangerous mix, because user can view anything added by any context processor.
Users accessing data they should not see through relations. When you pass model instance to template, its relations could be travesred futher than you could expect: {{ current_user.corporate_account.owner.ssn }} Oops...
A good preventive measure would be carefully reviewing your model relations to make sure you're not exposing something sensitive.
Overall, I'd say it is safe as long as you are aware of risks above and render user-supplied strings separately from regular templates. And make sure you eplicitly forbid {% debug %}, {% include %}. {% ssi %} template tags, as they can give away quite sensitive information. Maybe you can play it safe and only allow variables and filters and forbid control tags altogether.
include and ssi looks too dangerous for my taste, especially ssi which uses absolute paths. My opinion is that this is too risky business.
Well, from a server-side perspective it's safe (probably, no one has ever audited it), however the users could obviously generate any Javascript they wanted to perform XSS attacks.
It's not safe, the templates documentation says:
The template system isn’t safe against untrusted template authors. For example, a site shouldn’t allow its users to provide their own templates, since template authors can do things like perform XSS attacks and access properties of template variables that may contain sensitive information.
It runs deeper than just XSS attacks, or accessing user's data, if you try to do it, you will most probably have some vulnerabilities and you won't be aware of them.

Calling small app in template

Lets say I have a website with a small application that lists the 10 newest members, or something dynamic like that. I want this to view on every page, perhaps in a sidebar. How would i go about doing this.
My thoughts on the matter. I might not get the whole django thing just yet, but when I have a url like /foo/ calling a view bar - but what info do I have to send to the template from this view. Does every view have to send the info to the template (just so I can view my app) or is there someway to call this from the template instead.
I have tried to read through the documentation, but its seems I just can't understand this.
The usual way to provide '10 newest members' type of information from other apps is via a template tag. See this article by James Bennett on best practices (although note it's a bit out of date, as it was written before the inclusion_tag and simple_tag shortcuts were available).
Create a template tag that you can call on the page
Create a context processor and inject extra context variables onto each pageload
I'm sure there are other ways of doing this but those are probably the most logical two. The first gives you more power and will waste less processing time (for pages where you don't want to display the data) but a context processor is much more simple to write (you don't have to bend over backwards to please the template_tag gods).
Both are valuable things to know so there you go. Go and learn!
"Does every view have to send the info to the template (just so I can view my app)"
Yes.
"Is there someway to call this from the template instead."
No.
Your views are just functions. Functions can call other functions. That's ordinary good design. You can still do ordinary good design in Django.
You do have the ability to provide a "context". This is still done in the views to provide additional "context" for the templates. See http://docs.djangoproject.com/en/dev/ref/templates/api/#writing-your-own-context-processors for writing your own context processor.
Nothing (well almost nothing) is done in the template except render the objects provided by the view into HTML (or XML).
If you have a page that is an amalgamation of stuff from many small apps, then you have two tiers of apps.
Independent Apps.
Composite Apps that depend on Composite or Independent Apps.
Your composite app can call other app view functions to gather data.
Your composite app template can include other app template elements to present that data.
You have all the power of Python to decompose the independent apps into "data production" functions, view functions, template components and final page templates.
An independent app Page will use a view function and a template. The view function will use the data production functions. The template will use template components.
Decomposition still works, even in Django.

How can I put a block of dynamically generated content into a django template?

I want to include things like twitter status, or delicious tags, in my django templates.
These things are dynamic, yet regular. How would this be done?
There are a number of ways to handle this, so you can choose a method that best matches your own personal style or requirements:
Template context variable: as answered by Alex you can put your content into a context variable that is included in the context of every template created by every view. Django even provides a mechanism for doing this automatically, called a context processor. Pros: very straightforward. Cons: won't dynamically refresh new content on client browsers.
AJAX dynamic loading: as mentioned by Alex and Dave you can dynamically load your content using AJAX methods. As an example using jQuery, you would put a placeholder in your template something like <div id="twitterfeed"></div> and then in a javascript block in your template put $("#twitterfeed").load("{% url twitterfeed %}"); where twitterfeed is a url so named in your urls.py. Pros: will dynamically update browsers. Cons: can be tricky if you don't know Javascript.
Inclusion tag: Django provides a type of template tag called an inclusion tag, which is basically a custom template tag that can render dynamic content. In a way it's similar to a context variable, except your code to generate the content will only be called when you use the custom template tag in your template instead of being called for every view. Another benefit is the content is generated from a template of its own. You could do this with a normal context variable of course, but it's not as clean (IMHO) as using an inclusion tag. Pros: very straightforward, clean. Cons: won't dynamically refresh new content on client browsers.
The simplest approach is to use {{ mycontent }} in your template (where you want the dynamically generated content to appear) and put the correspondence between mycontent and its value in the context you use to render the template -- i.e., the most fundamental part of django's templating.
If what you mean is that you want Ajax support whereby Javascript on the page continuously refreshes such content according to what the server wants it to be at any given time, I suggest looking into dojango, the Dojo/Django integration project -- it's not yet as fully mature as each of Dojo and Django are on their own (not version 0.4 yet), but it is already usable and useful.
A common technique is to leave a placeholder div in the generated content, then fill the div in on the client side via an AJAX call from Javascript that you include in the page.
That gives you the benefit of having a cacheable (fast loading) primary page, with separate dynamic bits. Depending on how live you want the dynamic bits, you can can even cache them for shorter durations.

How can I pass a standard, static variable from all views in Django?

I'm working on a blog application, and I want to have a sidebar that includes a list of all the months the blog has been in existence, to provide links to archives pages. Moreover, I'd like to make this automatically update when the month changes, rather than hardcoding it in the template. Of course, as far as I can tell, this means that I'll have to calculate the list of months in every view, and pass it into every template from every view.
I'd like to avoid this, if possible. Is there a way to calculate the list once and automatically apply it to every template, without having to explicitly pass it into the template from every view?
There are a few possible solutions to your problem.
If you really want to have this on every page on your site a context processor is probably your best choice. Context processors are basic way to inject data into all template contexts. Be aware however that the context processor will be called on every request.
An alternative solution would be to create a custom template tag and use it on a shared base template for all of the pages you wish to have your sidebar. Template tags are a bit more complex to create but they are more flexible.
With either solution you should also look at Django's cache framework. The cache framework makes it pretty easy to temporarily store your calculated values for a while to save some work on each request.
You want a template context processor
Django - having middleware communicate with views/templates
http://docs.djangoproject.com/en/dev/ref/templates/api/?from=olddocs#id1
Django's template inheritance should cover this. You could create a base template that handles your sidebar functionality. Your other views extend this template.
Template Inheritance:
http://www.djangobook.com/en/1.0/chapter04/#s-template-inheritance
A combination of custom template tags as mentioned previously and template fragment caching should do the trick.