How to write a custom decorator in django?
Solution 1
You don't have to write your own decorator for this as user_passes_test
is already included in Django.
And there's a snippet (group_required_decorator
) that extends this decorator and which should be pretty appropriate for your use case.
If you really want to write your own decorator then there's a lot of good documentation on the net.
And well, to (re-) use the decorator just put your decorator in a module on your path and you can import it from any other module.
Solution 2
Played around with the various links above and couldn't get them working and then came across this really simple one which I adapted. http://code.activestate.com/recipes/498217-custom-django-login_required-decorator/
from functools import wraps
from django.http import HttpResponseRedirect
def authors_only(function):
@wraps(function)
def wrap(request, *args, **kwargs):
profile = request.user.get_profile()
if profile.usertype == 'Author':
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect('/')
return wrap
Using @wraps
is better than manually overriding like doing wrap.__doc__ = fn.__doc__
. Amongst other things, it ensures your wrapper function gets the same name as the wrapped function.
See https://docs.python.org/2/library/functools.html
Solution 3
Thanks to arie, the answer helped a long way, but it doesn't work for me.
When I found this snippet, I got it to work properly: http://djangosnippets.org/snippets/983/
This solution worked for me:
The helper function
This function has the benefit of being reusable in other places, as a drop in replacement for user.is_authenticated
. It could for instance be exposed as a template tag.
def my_custom_authenticated(user):
if user:
if user.is_authenticated():
return user.groups.filter(name=settings.MY_CUSTOM_GROUP_NAME).exists()
return False
The decorator
I just put this at the top of my views.py
, since it's so short.
def membership_required(fn=None):
decorator = user_passes_test(my_custom_authenticated)
if fn:
return decorator(fn)
return decorator
Using it
@membership_required
def some_view(request):
...
Solution 4
See examples in django itself:
http://code.djangoproject.com/browser/django/trunk/django/contrib/auth/decorators.py
Your particular example is probably just a version of 'user_passes_test' where the test is going to be membership of the 'premium' group.
To use anywhere, make a python package and import it from there. As long as its on your sys.path it'll get found.
Solution 5
http://www.makina-corpus.org/blog/permission-required-decorator-django
i based mine off that blog post.
Stick that in a file in the python path or in a "util" app and import it into views:
e.g.
project_dir
|_ app1
|_ app2
|_ utils
|_ __init__.py
|_ permreq.py
from util.permreq import permission_required
@permmission_required('someapp.has_some_perm', template='denied.html')
def some_view(request):
blah blah
user677990
Updated on February 02, 2022Comments
-
user677990 over 2 years
The problem -
@is_premium_user def sample_view: ....... ......
I want certain views accesible to only the premium users of the website.
And how can I use this decorator across various applications in my project? -
dting about 13 yearsYou can write them into your models, docs.djangoproject.com/en/dev/topics/auth/#custom-permissions and manage them through the admin or django shell
-
user677990 about 13 yearsdef souk_required(): """Requires user membership in at least one of the groups passed in.""" def has_souk(u): if u.is_authenticated(): if bool(SoukUsers.objects.get(person = u)): return True return False(u) return user_passes_test(has_souk)
-
user677990 about 13 yearsit gives this error - souk_required takes no arguments (1 given)
-
arie about 13 yearsHm .. i accidentally upvoted your comment ;-) Well, you removed the expected argument from you function definition and therefore receive the given error. So, what about creating a group "premiumusers" and adding your users to that group? Then you can use the snippet as it is and just pass in the name of your group.
-
user677990 about 13 yearsIts not your fault it happens to the best of us ; ].... anyways thanks a lot man... I owe you an awful lot of time.
-
radtek almost 10 yearsThis should be the accepted answer, thumbs up! I tried to piggy back off the user_passes_test decorator but got lost, this saved the day.
-
Ardian almost 9 years@radtek i got
wrap() takes at least 1 argument (0 given)
. Any clue to solve it? -
radtek almost 9 yearsWould have to see your code, but most likely you didn't pass request to your function you are decorating.
-
Sven about 4 yearsthe
@wraps
method is just for docs, so you could leave it out, right?