I have a website running Django whose main domain is example.com. What I want to achieve is to behave in a different way when an user access from example2.com (specifically loading custom CSS).
I understand that I have to make some changes to the web server and that is not a problem. My question is focused on how to accomplish this with Django.
There is something called Django sites that could be useful for this, but I am not sure if this is an overkilling feature for such a "simple" thing. However I am aware that multiple changes would be needed (paths, cookies domain, etc), so... is this the recommended way to do it?
It's a pretty simple thing to accomplish. You have a few different options.
Checking the HTTP_HOST straight from a template
A very simple approach would be from a template to check the request.META dictionary's value for the HTTP_HOST key.
{# Anything other than port 80, HTTP_HOST will also include the port number as well #}
{% ifequal request.META.HTTP_HOST 'example2.com' %}
<!-- your css imports here -->
{% endifequal %}
Remember, this is set by the client though, so if you were doing anything else that was security-sensitive, this would NOT be the approach to use. Just for loading some CSS though, it would be fine.
Custom middleware
Another option would be to create custom middleware and check this same object from there. Basically the same process but you'd probably want to do something like set an extra key on the request object
In some file.. yourproject/someapp/middlware.py
class DomainCheckMiddleware(object):
def process_request(self, request):
if request.META['HTTP_HOST'] == "example2.com":
request.IS_EXAMPLE2 = True
else:
request.IS_EXAMPLE2 = False
return None
In your settings.py
MIDDLEWARE_CLASSES = (
# whatever middleware you're already loading
# note: your middleware MUST exist in a package that's part of the INSTALLED_APPS
'yourproject.someapp.DomainCheckMiddleware'
)
In your template
{% if request.IS_EXAMPLE2 %}
<!-- load your css here -->
{% endif %}
This is more legwork, and pretty much does the same thing, but you could easily apply some extra tests to see if you're in debug mode or just accessing over localhost:8000 and still set IS_EXAMPLE2 to true, without making your templates more difficult to read.
This also has the same downfall mentioned previously.
https://docs.djangoproject.com/en/dev/topics/http/middleware/
Using the sites framework
Using the sites framework is only valid if you have enabled it (django.contrib.sites) enabled, which it no longer is by default and is overkill for your purposes. You can see an example of how that would work from this answer though:
How can I get the domain name of my site within a Django template?
Related
My Django app contains a couple of external references, e.g. to the application's blog, which is not part of the Django codebase and is hosted on a different subdomain.
So far, links to these were spread all around the source code as direct absolute URLs.
Now I was wondering if there was a way to use Django's excellent URL routing system for these external URLs as well. I thought I could define them like this:
url(r'^permalink/blog/$', RedirectView.as_view(url='https://blog.example.com'), name='blog'),
Then I could just reference them as {% url 'blog' %} in my templates. That works.
Now I was wondering if there was a way to resolve these directly to the 'final' URL with a special (self-defined) template tag, so that they appear as https://blog.example.com to the user, as opposed to /permalink/blog/ (to the browser) or https://app.example.com/permalink/blog/ (to the user). I do already have a self-defined {% absolute_url %} template tag, which I use in templates that require absolute URLs, like transactional email.
However, I couldn't find a way to reverse a named URL (like external:blog) to its urlpattern as opposed to its final relative URL. To do this myself, it seems like I'd have to duplicate all the code from URLNode.render(), plus urlresolvers.reverse plus probably parts of RegexURLResolver._reverse_with_prefix(). That's quite a bunch of code, but I didn't see a simpler entry point/hook into the system. Did I miss a trick there?
To summarize, I'm basically looking for a function that I can pass a named URL to, e.g.
external:blog
and get a RegexURLPattern instance back, e.g.
RegexURLPattern(r'^permalink/blog/$', RedirectView('https://blog.example.com'), {}, 'blog')
or maybe just the view might work, too.
We want one Django instance to serve different domains. The only difference between them is different templates, all the rest is the same. So we tried to just modify TEMPLATES.DIRS in a middleware. But Django templates loader ignores all the changes in TEMPLATES.DIRS made after settings.py is loaded.
Is there more or less standard Django Way to support different TEMPLATES.DIRS for different domains with just one settings.py?
To solve your problem use a template variable, both extend and include support variables. Just omit the quatation marks:
{% extends "base.html" %}
becomes
{% extends string_variable_with_file_name %}
Of cause you have to set that variable to the right filename in your context.
I'm developing a web application with Django and we have met a dilemma about the design.
We were making one template for every screen, but right now we have detected that some parts of of the screen with the information are repeated all over the different screens. For example, when coming to show personal data of a person, you can show also another data concerning that person, but not personal data (financial data, for instance).
My intuition told me that we should look for a solution in which we could make small templates that we could compose, combine and concatenate and that we should also make different views or functions which would return its own associated template each one.
Thus, person_data() would return the rendered template showing the name, surname, address, etc... and financial_data() would return the rendered template showing the salary, bank account, etc... After that, the desirable thing would be concatenating both or inserting them in a wider template for showing all this together.
<html>
...
{# Html code here #}
...
{# person_data template #}
...
...
{# financial_data template #}
...
{# Html code here #}
...
</html>
So as always I made some research on the net and I found:
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include
a link which describes how to use include for inserting a template file in another template:
{% include "foo/bar.html" %}
And you can also use a variable from the python function with the path name or an object with render method:
{% include template_name %}
So we could use all this in this way for combining, concatenating, composing and operating on templates. We could choose the one which includes the others and passing it the context for all templates (I suppose, I didn't test anything). But I don't know if I'm well directed or if this is the best way to go. I would appreciate some advice.
I also found another interesting thread in stackoverflow talking about this:
How do you insert a template into another template?
My idea is to have small templates which are used repeatedly in different spots of the web and composing them in Unix-like style, so I would have small visual pieces that would be used once and again saving a lot of hours of writing of code.
Please some advice.
Thanks in advance
Yes, that is a correct approach. I think the best solution is to combine {% include %} and {% extend %}, which will allow you to inherit from a base template (via extend), and include parts you want from other templates (via include).
You'd end up having a base template, a template for the header, the footer, parts of the body etc.
You might also want to read more about it here and here
I know Django has already a good templating system for designers but I wonder if it is possible to limit the usage of certain template tags and filters.
We are building a Django plugin for designers to make template developing more open, but we want to hide some logic of django template system and expose just the necessary to the designer.
In example: How can I prevent the use of {% load %} template tag and preload only the tags that I want?
Try this decorator: Safe template decorator
From author description:
A decorator that restricts the tags and filters available to template
loading and parsing within a function.
This is mainly meant to be used when granting users the power of the
DTL. You obviously don't want users to be able to do things that could
be potentially malicious.
The {% ssi %} tag, for example, could be used to display sensitive
data if improperly configured.
{% load %} gives them access to all the unlimited python code you
wrote in your templatetags. {% load sudo %}{% sudo rm -rf / %} o_0
Note that the "load" tag (among others) is not listed in the default
tag whitelist. If you parse a template (however indirectly) in a
function decorated with this, unlisted builtin tags will behave like
undefined tags (ie, they will result in a TemplateSyntaxError).
Since {% load %} is not whitelisted, you may want to include some
custom tags or filters as "builtins" for convenience. Simply put the
module paths to the libraries to include in the extra kwarg or the
extra_libraries list. Generally, this is not recommended, as these
libraries need to be carefully and defensively programmed.
NOTE: This does not do anything about cleaning your rendering context!
That's completely up to you! This merely restricts what tags and
filters are allowed in the templates.
Examples:
from django.template.loader import get_template
safe_get_template = use_safe_templates(get_template)
tmpl = safe_get_template('myapp/some_template.html')
from django.template import Template
use_safe_templates(Template)('{% load sudo %}')
# TemplateSyntaxError: Invalid block tag 'load'
An easy way would be to implement your own template loader similar to Django's file system loader and strip certain tags out of the text (guess you could event turn into a template/template nodes when doing so to be able to parse it correctly) before giving the template to Django for further processing.
Is it advised or redundant to set permissions on the template AND the view?
Consider that any data manipulation to the DB is done through POST
if the following enough for permissions?
{% if perms.system.view_employee %}
<!-- content here -->
{% else %}
<h1>Sorry you do not have permission to access this page<h2>
{% endif %}
or should I also implement server side checking as well (is it redundant to do so or necessary)?
def my_view(request):
if not request.user.has_perm('polls.can_vote'):
return HttpResponse("You can't access this page")
else:
# do stuff
...
Checks in the template are server side.
Permissions checks in the template and in the view do not have the same purpose:
Checking permissions on the view will disallow the access to the entire page. You do this when this page, and the featured it embeds, is for APO. You handle ressources access.
Checking permissions in the template disallow parts of the template to be displayed. You do this when you want people to be able to access the page, but there are some stuff you don't want them to see on the page. You handle display.
In your particular example, you must set the permissions checks on the view to dissallow anybody to do this manipulation. Usually, if the views is accessed using POST their are little chances you want template permission checks because POST requests are actions by essence.
You usually will want template permissions checks if you:
have some parts of the page the person is not allowed to see (like sensitive data)
want to improve usability to show elements (menu, forms, etc) that are relevant only to its level of permission. Indeed it's useless to display a link to the admin in the menu if the person doesn't have the right to access the admin.