61👍
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.
87👍
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.
- [Django]-Django: "projects" vs "apps"
- [Django]-How can I call a custom Django manage.py command directly from a test driver?
- [Django]-Cannot set Django to work with smtp.gmail.com
6👍
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):
...
- [Django]-Celery discover tasks in files with other filenames
- [Django]-New url format in Django 1.9
- [Django]-Django: accessing session variables from within a template?
3👍
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.
- [Django]-Django TextField and CharField is stripping spaces and blank lines
- [Django]-Resource temporarily unavailable using uwsgi + nginx
- [Django]-How to stop autopep8 not installed messages in Code
2👍
Here is a slightly different implementation, which allows additional parameters in order to specify which page to redirect to when validation fails, and which message to display to the end user:
from functools import wraps
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from core.helpers.flash import send_flash_error
def lender_only(redirect_to='plateforme.views.vue_login', error_flash_message=None):
def inner_render(fn):
@wraps(fn) # Ensure the wrapped function keeps the same name as the view
def wrapped(request, *args, **kwargs):
if request.context.user.is_authenticated and request.context.user.is_lender:
return fn(request, *args, **kwargs)
else:
if error_flash_message:
send_flash_error(request, error_flash_message) # Replace by your own implementation
return HttpResponseRedirect(reverse(redirect_to))
return wrapped
return inner_render
# Usage:
@lender_only('vitrine.views.projets', {'message': "Oops, can't go there."})
def render_page_index(request):
This guide helped me getting through it: https://elfsternberg.com/2009/11/20/python-decorators-with-arguments-with-bonus-django-goodness/ alongside the previous answers
- [Django]-Django MultiValueDictKeyError error, how do I deal with it
- [Django]-How can I list urlpatterns (endpoints) on Django?
- [Django]-What is the difference between null=True and blank=True in Django?
1👍
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
- [Django]-Table thumbnail_kvstore doesn't exist
- [Django]-Open the file in universal-newline mode using the CSV Django module
- [Django]-Django Rest Framework, passing parameters with GET request, classed based views
1👍
from django.contrib.auth.decorators import user_passes_test
from django.core.exceptions import PermissionDenied
def perm_group_required(group, login_url='/', raise_exception=False):
def check_group(user):
if user.groups.filter(name=group).exists():
return True
# In case the 403 handler should be called raise the exception
if raise_exception:
raise PermissionDenied
return False
return user_passes_test(check_group, login_url=login_url)
@perm_group_required('add_customer_group')
#group name="add_customer_group"
def employee_add_customer(request):
##logic
...
- [Django]-What is "load url from future" in Django
- [Django]-Django – iterate number in for loop of a template
- [Django]-Best way to make Django's login_required the default
0👍
For example, with the custom decorator @tran
below, test()
can be run in transaction. *You can see my answer explaining about a custom decorator in detail:
# "views.py"
from django.db import transaction
from django.http import HttpResponse
def tran(func): # Here
def core(request, *args, **kwargs):
with transaction.atomic():
return func(request, *args, **kwargs)
return core
@tran # Here
def test(request):
person = Person.objects.all()
print(person)
return HttpResponse("Test")
- [Django]-How to allow only one radio button to be checked?
- [Django]-In Django, how do I check if a user is in a certain group?
- [Django]-Manager isn't accessible via model instances