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.
Related
I need to replace same plugin template on different subpages - e.g. on frontpage I need specific slider template for latest articles, in detail article I need small list, on search result without images etc.
[note: everything about aldryn newsblog app - I don't mean my own plugin!]
*(something like custom template per plugin instance)
How to replace it ? Extending template is not quite what I need - inheritance is from bottom - from lower subtemplate to base.html - but that plugin have hardcoded lower template.
Tons of IF block in template is irrational then we think in MVC.
*( like here Render Django-CMS plugins differently on different splaceholders/templates )
Or maybe just write custom template with using hardcoded including plugins ? But using django cms placeholder editor is very useful and it'll be better to keep working in that way :///
So, I create front.html base template for frontpage,
put some plugins to placeholders - and need to replace subtemplates for this plugins only in this front.html and keep subtemplates for that plugin in other places - this is main goal.
It will be the best, when django cms / aldryn newsblog provide option "custom template" per plugin instance :|
( like this one http://www.ilian.io/django-cms-plugins-with-selectable-template/ )
If I understand your question correctly (it's late here), you need a way to override plugin templates on a plugin instance basis because hacking django templates is not the way to go (I agree).
Django CMS does allow you to override plugin templates on an instance basis.
As shown in http://docs.django-cms.org/en/develop/how_to/custom_plugins.html?highlight=get_render_template#the-simplest-plugin
In your CMSPluginBase subclass add the following:
def get_render_template(self, context, instance, placeholder):
# criteria goes here
return 'sometemplate.html'
As far as how to know which template to render when (criteria), you can do a few things.
Use the page's reverse id:
page = instance.page
templates = {
'homepage': 'plugin_home.html',
'about': 'plugin_about.html',
'contact': 'plugin_contact.html',
}
return templates[plugin.page.reverse_id]
This approach has a few drawbacks:
Relies on plugin being bound to a page. (plugins can live outside of pages)
Can only work with pages that have reverse id set and reverse ids
are unique per page which means you would have to list reverse id
for every page you want to change template for.
Use a page extension to set a category per page:
Checkout http://docs.django-cms.org/en/develop/how_to/extending_page_title.html
With this approach you can then set some sort of category to multiple pages and so you can target multiple pages in one shot like so:
page = instance.page
extension = get_page_extension(page) # Check out docs for this
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[extension.category.name]
Pros:
Can target multiple pages in one shot
Cons:
Relies on plugin being bound to a page.
A bit more complex
Use a template context variable:
In your templates, depending on how you're rendering your plugins, you can
provide a context variable like so:
{% with category='category_1' %}
{% placeholder 'content' %}
{% endwith %}
or
{% with category='category_1' %}
{% render_plugin yourplugin %}
{% endwith %}
Then in your get_render_template method you can access this context variable and do the following:
# Use .get() to provide fallback
category = context['category']
templates = {
'category_1': 'plugin_category_1.html',
'category_2': 'plugin_category_2.html',
'category_3': 'plugin_category_3.html',
}
return templates[category]
Pros:
No extra models.
Can target multiple pages in one shot.
Cons:
The only one I can think of is these random {% with %} in
templates.
I completely missed the newblog part, so in order to override the newsblog plugins or any plugin, just subclass the plugin class you want to override and unregister the original and then register yours, make sure yours has the same class name.
Maybe you can make the whole template logic above into a mixin to use throughout your project.
I've always wanted to give Zinnia a look, but I'm too far into working with NewsBlog on a site right now to do it (and blogs have already been posted and whatnot). You can always just add a few extra placeholders in the template (it's not the most efficient looking thing ever, but it's no load on the framework if you add a placeholder and leave it blank), that way they aren't static, and then you can put whatever plugins you want to inside of them. You can customize each component in NewsBlog pretty easily by just adding whatever you want in the structure mode. Things get trickier when it comes to having multiple blogs that act differently, but even then, as long as you're not adding components into the static placeholders provided by NewsBlog (or as I so elegantly learned it, "don't put the stuff in the blocky-things with the pins next to them), you can create different namespace for the different blogs (either in the admin, under "Configs" in the NewsBlog section, or when creating a new page and hooking it to the NewsBlog app), and you can have different templates on different blogs.
EDIT: This is a really excellent resource for touching up NewBlog without throwing the baby out with the bathwater (after three months of learning DjangoCMS, I'm still finding myself referencing it for fine-tuning pieces of NewsBlog, and to refresh my grasp on templatetags and other things that are overwhelming and have quickly left my brain along the way): https://www.django-cms.org/en/blog/2016/02/16/build-a-website-without-knowing-python-django-part-two/
*I linked to part two, as the first part deals with how to initially setup a project, and I assumed it probably wasn't relevant. Then again, if you're using Aldryn, there are some useful bits in there that can extrapolate if you're having trouble with customizing the boilerplate (or other things you'd like to configure that an Aldryn setup handles for you -- which is super awesome most of the times, but when it's not super awesome, it's usually super frustrating :)
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.
My question is a bit generic in that my problem is a broad one. I have been working with django for some time, and I really want to move more into doing very dynamic web pages where actual page reloads aren't common.
I have read about the different popular javascript frameworks available, and I always feel like I am missing part of the puzzle, particularly in templating.
What are some of the best practices for keeping my templating code as non redundant as possible. I get the impression that a lot of templating logic will make it's way into the JS in addition to my django templates. I want to avoid situations where I am writing templating code in two different places.
For a very basic example, let's say I am writing some template code inside Django for an input field that has a set number of attributes. I have then also written in JS that when I click on a button, another input field of the same type is generated with all the appropriate attributes. In practice this could be a form that takes an arbitrary amount of e-mail addresses. The problem I see is that when I want to change something about that input field, I need to do it in two places.
Is there a particular development paradigm or work flow that I am unaware of? How are issues like this generally avoided?
Recommendations on frameworks would be amazing too!
as you mentioned above:
Use Django Template language. Pass the data from view to template dynamically.
Read Django Template Language documentation.
For JS :
its better to write your js in home.html.... use {% include %} tag for other html
How to create something like this:
If user is in:
http://127.0.0.1:8000/about/ then in my base.html I have:
You are here: <li>Home</li>
Etc.
Is there a simple way?
This can get tricky, depending on what you mean by "breadcrumbs".
Django's URL routing system has no inherent hierarchy since any URL can map to any view.
So the "hierarchy" has to be completely specified by you.
…and passed by you to the template in either your view, or in a context processor.
You'll want to assign both a URL AND a name for the URL (so you know /about/ is "Home").
There are a bajillion ways to do this, and it all sort of depends on how flexible you want it, how complicated your URL patterns get, whether you want to support nesting, etc.
Normally, I just use Django Breadcrumbs. This project handles all of the weirdness of breadcrumbs, has a very easy to use API, and handles even weird cases.
While a full code sample would probably be helpful, it's a long and thorny problem, so you're better off reading the documentation for django-breadcrumbs, and then returning here with questions.
I've got an existing Django site, with a largish variety of templates in use. We've agreed to offer a custom-skinned version of our site for use by one of our partners, who want the visual design to harmonize with their own website. This will be on a separate URL (which we can determine), using a subset of the functionality and data from our main site.
So my question is: what's the best way to add reskin functionality to my site, without duplicating a lot of code or templates?
As I see it, there are several components which need to work together:
URL: need to have a different set of URLs which points to the partner-branded version of the site, but which can contain all the standard path info the site needs to build pages.
Template 'extends': need to have the templates extend a different base, like {% extends 'partner.html' %} instead of {% extends 'base.html' %}
View logic: need to let the views know when this is the partner-branded version, so they can change the business logic appropriately
My idea so far is to put the partner site on a subdomain, then use a middleware to parse the domain name and add 'partner' and 'partner_template' variables to the request object. Thus, I can access request.partner inside my views, to handle business logic. Then, I have to edit all my templates to look like this:
{% extends request.partner_template|default:'base.html' %}
(According to this answer, 'extends' takes a variable just like any other template tag.)
Will this work properly? Is there a better way?
If you are using different settings.py for the different sites you can
specifiy different template loading directories. (Which may default to your unskinned pages.)
Personally I'm not convinced by having different business logic in the same view code, that smells like a hack to me - the same as extensive conditional compilation does in C.
So to sum up.
Use django.contrib.sites and different settings.py
Get a clear idea, how much this is a new app/website using the same data, or just different css/templates.