Django templates - is it possible to make url-aware templates - django

Is it possible to make a django template URL aware without javascript?
For example, I would like to modify the css class to "active" for a certain tab or pill in twitter bootstrap.

If you have request available in context then you can use request.path within the template to know the url and make css class active or inactive based on that.
You need to add django.core.context_processors.request in your TEMPLATE_CONTEXT_PROCESSORS in project settings.
Alternatively just pass a page_name in request context and use that.
As arie pointed out: check django-activelink which basically seems to use the same above approach I mentioned but it adds some template tags on top.

Yes you can do that, but the resulting template code will be a bit hard to read. Adding a lot of logic to the template reduces/removes the separation-of-concerns advantage of MVC.
What you need to do is pass the request info to the template, and the easiest way to do that is to add a template context processor. Put something like this in your settings.py:
from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS += (
'django.core.context_processors.request',
)
You can then access the request.path info in your template and construct logic to alter the output depending on your needs.

Related

django add context based on request to all views

I need to render my site without navbar if there is an argument in the request like nv=false and I want to pass a variable to context based on this so that the main template shows the block or not. my site also has lots of json-rpc functions, and I don't want to add extra overhead on it. how can I do this without rewriting all my views? (they are not class based and my site uses django 1.8)
Just add context processor that will add this variable to context. Context processor is a simple python function
def navbar(request):
return {'navbar_enabled': request.GET.get('nv', False)
and add it to the list of template context processors
TEMPLATE_CONTEXT_PROCESSORS = (
...
'MODULE_NAME.navbar',
...
)

Is it possible to give external URLs names in django

I have just started naming my URL patterns in Django, so that if I want to change the URL pattern, I just have to change it in one place. e.g:
url(r'^$', HomeListView.as_view(), name='home'),
And referencing it in my templates like this:
{% url home %}
Is this possible with external links in case they change or I change the a Facebook page link for example. How would this look?
Thanks
One way to do this could be to write an external_url template tag, and have an ExternalURL model that stores them.
This would give you the advantage of being able to have the urls editable without redeploying changed code.
The disadvantage is that there will be database lookups to see those urls. Also, you would need to {% load external_urls %} in templates you want to use it in.
# models.py pseudo-code
class ExternalURL(models.Model):
name = models.CharField(unique=True)
url = models.URLField()
Your template tag might look something like:
# app/templatetags/external_url.py
#library.register()
def external_url(name):
try:
return ExternalURL.objects.get(name=name).url
except ExternalURL.DoesNotExist:
return ''
Another alternative could be to have a Context Processor that stores them all in the context, allowing you to not have to pass them explicitly into views: would be useful if you had several external urls that were used in many places within your system.
def external_urls(request):
return {
'google': 'http://www.google.com/',
# more here
}
The advantages of this is no database lookup, no requirement to load the template tag, but you will need to add it to your settings.CONTEXT_PROCESSORS. Also, you could inspect request to see if the current user may see all the urls.
If its external links, and possibility of the change then you should define it in settings or separate static url file and pass those variable with request context.
urls.py should be recommended to use only for your app specific urls.
In this SO thread you can see how to approach defining constant

Conditional tags in templates

I'm using Django on top of an existing database/user framework so unfortunately it is not possible to me for use the django auth framework.
I have my custom auth library built, now I just need to figure out how to use it in templates. Certain links should only appear for users who have access to it.
In PHP I could do soemthing like this
<?php if auth('RestrictedLinkName') {?> <?php } ?>
What is the Django way? I have been playing with custom tags but haven't been able to get it working yet. I was thinking something like:
{% if check_permission('Restrictedarea') %} hjkfgdkhfg {% endif %}
If you need to evaluate check_permission('Restrictedarea') then do it in the view function and pass the evaluated result in the template.
The djangobook says (in Chapter 4: Templates, in Philosophies and Limitations section) -
Business logic should be separated from presentation logic. Django’s
developers see a template system as a tool that controls presentation
and presentation-related logic – and that’s it. The template system
shouldn’t support functionality that goes beyond this basic goal.
For that reason, it’s impossible to call Python code directly within
Django templates. All “programming” is fundamentally limited to the
scope of what template tags can do. It is possible to write custom
template tags that do arbitrary things, but the out-of-the-box Django
template tags intentionally do not allow for arbitrary Python code
execution.
And if need to write custom tags check these links:
Writing a Template Tag in Django
Custom template tags and filters
You can write your custom template tags and filters. But this may help you up to a point, for further, you must write your custom context_processors (and custom middlewares if needed.)
But doing authentication and permission check through custom function is quite hard, but possible. I have a system fully runs on custom authentication/authorization.
First of all, you can examine django context_processors to understand how they work. then you can write your custom context_processor. After you add your context processor in your settings, you can use those methods, and do your authentication/authorization as you wish.
One of my custom contect_processor function is like:
from django.utils.functional import lazy
def CustomProcessor(request):
cust_perms = {
'admin_perm_check': lazy(lambda: myCustomPermChecker(request), myCustomPermChecker)(),
'system_admin': aFunctionToReturnBoolValue(),
}
return custom_perms
class myCustomPermChecker(object):
def __init__(self, request):
self.request = request
def __getitem__(self, perm_name):
return True if (perm_name in user_perm_list()) else False
In your template
{%if admin_perm_check.perm_name%}...{%endif%}
{%if system_admin %} this is a bool check{%endif%}
You must define your permchecker as a class, which have __getitem__ method so, your template tag admin_perm_check.perm_name could work. This perm checker accepts only one additional paramater (perm_name), If you want to use django-style two parameter check then you must do:
class myCustomPermChecker(object):
def __init__(self):
pass
def __getitem__(self, module_name):
return SecondPermCheckerStep(module_name)
class SecondPermCheckerStep(object):
def __init__(self, module_name):
self.module_name = module_name
def __getitem__(self, perm_name)
return True if ('%s.%s' % (self.module_name,perm_name) in user_perm_list()) else False
{%if admin_perm_check.module_name.perm_name%}
You can use another class.__getitem__ to add one more key to tour tag chain in your template etc.
Since your context_processor CustomProcessor(request): accept http.request object as a parameter, you can pass your methods or functions any value (session id or user id etc.) that will be required in authenticaon or authorization. You can write a middleware to set custom values to your request object to use (like django set user instance and let you use request.user in your views.). You can also set your custom user model instance so you can use it in you template (if you set it in your request_context) and in your views (if you set it in your middleware)
Reading docs could not help here much, better is checking django code to see how django handle this.

Django's equivalence of ASP.NET UserControl

If anyone here is ASP.NET pro, you might know what I mean by user control. I wish to create a similar one in django instead.
So, my problem is that I have several pages in my website, but I need a search bar to appear in every pages. Since I require the views.py to operate this search bar, I cannot do a simple method of
{% include 'something.html' %}
Therefore, can anyone suggest how can I do it?
There are a couple of ways to accomplish what you're wanting to do:
Context Processors
Template Tags
Context Processors can augment the template context with values, regardless of which template is loaded. They are akin to filters in Rails.
Template Tags, like Context Processors, can accomplish anything you can do in Python, but are implemented at the template level.
If you need something to be present on every template, one of the simplest ways to accomplish this is with an inclusion tag, which can also accept values passed to it. An inclusion tag could be implemented at your highest level template, a.k.a your MasterPage, and as long as you don't put it in a block and override it, it would appear on every page that includes that template in its inheritance chain.
If it's just something you want to include on every page, and it doesn't need to do any processing, you should just be able to place the code you want in the top-most template and have subsequent templates inherit that.
I typically have a "base.html" template that all of my templates inherit from. If I need something to be in every page, I put it there. If it's something I want there by default, but want to be able to augment it in subsequent templates, I will place it into a block. That block will let you include or override its default content.
I know this post is kind of old but I just came across it and found a kind-of-solution that works. I call it kind-of-solution because it is a workaround.
I have a few different sites on which I want to display logging information. This display always looks the same (it has the same html) and has the same database table and model class behind it.
My solution/workaround uses the django filters:
in views.py I put the list of log-entries in the context
context = {'list_log': Log.objects.filter(condition = True) }
template = loader.get_template('my_html_file.html')
return HttpResponse(template.render(context, request))
in my_html_file.html I use a custom filter
{{ list_log|get_log_uc|safe }}
in the filters.py I load another html file with this custom filter
#register.filter
def get_log_uc(list_log):
template = loader.get_template('user_control_log.html')
context = { 'list_log' : log }
return template.render(context)
in user_control_log.html I have the user control equivalent html
{% for log in list_log %}
<p>log.something</p>
{% endfor %

Django Templates: With Template AutoEscaping on, do I need to pass URLs to URLEncode?

I am running Django trunk and have template Autoescaping on (default). Do I need to pass template URLs to the URLENCODE filter, or does Autoescape take care of that automatically? The Django docs aren't clear.
Django docs say this about Autoescape:
When auto-escaping is in effect, all variable content has HTML escaping applied to it before placing the result into the output (but after any filters have been applied). This is equivalent to manually applying the escape filter to each variable.
Yes, autoescaping is related only to HTML content. URL encoding is another story.