user2355278
user2355278

Reputation: 395

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') {?> <a href=""></a> <?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 %}

Upvotes: 1

Views: 302

Answers (2)

Mp0int
Mp0int

Reputation: 18727

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.

Upvotes: 1

Rupak
Rupak

Reputation: 3674

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:

Upvotes: 1

Related Questions