simplifying double decorators?

47 views
Skip to first unread message

Richard Brockie

unread,
Nov 30, 2014, 1:31:12 PM11/30/14
to django...@googlegroups.com
Hi,

I'm running into the situation where I have several views with the same set of decorators:

@login_required()
@user_passes_test(some_test_function, login_url='/', redirect_field_name=None)
def some_view(request):
    # some code
    return render(request, 'some_template.html', locals())

How would I go about combining the two (or more) decorators into a single decorator that can be used instead and retain the functionality?

IE: this:

@login_required()
@user_passes_test(some_test_function, login_url='/', redirect_field_name=None)
def some_view...

becomes abstracted to something like this:

@my_custom_decorator_with_redirects()
def some_view...


--
    R.

Richard Brockie

Collin Anderson

unread,
Nov 30, 2014, 2:28:57 PM11/30/14
to django...@googlegroups.com, ric...@ontheday.net
Hi,

def my_double_decorator(view):
    view
= user_passes_test(some_test_function, login_url='/', redirect_field_name=None)(view)
   
return login_required()(view)

Collin

Arnold Krille

unread,
Nov 30, 2014, 2:49:58 PM11/30/14
to django...@googlegroups.com
On Sun, 30 Nov 2014 10:30:29 -0800 Richard Brockie
<ric...@ontheday.net> wrote:
> I'm running into the situation where I have several views with the
> same set of decorators:
> @login_required()
> @user_passes_test(some_test_function, login_url='/',
> redirect_field_name=None)
> def some_view(request):
> # some code
> return render(request, 'some_template.html', locals())
>
> How would I go about combining the two (or more) decorators into a
> single decorator that can be used instead and retain the
> functionality?

Well, if the user has to pass a test, you have to have a user first.
And unless the AnonymousUser passes your permissions tests, the
combination of "@login_required" and "@user_passes_test" is a
redundancy… At least it was in my old project I worked for where we
replaced these duplicates and used only the permissions tests and it
worked great. No user -> no permissions to check for. (Actually it was
no user -> no company & no roles -> no permissions.)

Have fun,

Arnold
signature.asc

Richard Brockie

unread,
Nov 30, 2014, 3:19:07 PM11/30/14
to django-users
Hi,

Thanks for the responses.

@Arnold:

The way I see this working is that @login_required decorator prompts the user to login if they are not already. If there is a valid user who fails the test, they login correctly, but are redirected to the homepage.

Without the @login_required, there is no prompt to login. I'm anticipating these pages being bookmarked and would like the user to be taken directly to the expected page after a successful login.

@Collin:

Thanks for the suggestion - that works!. New to me is the ...)(view) syntax. Do I understand correctly that I could add another line following the same structure and reversal of order? Eg:

@decorator1(kwarg1='testing')
@decorator2(kwarg2='something')
@decorator3
def my_view...

becomes:

def triple_decorator(view):
    view = decorator3()(view)
    view = decorator2(kwarg1='something')(view)
    return decorator1(kwarg2='testing')(view)

@triple_decorator()
def my_view...


Thanks very much!

R.



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/20141130204816.48a79081%40xingu.arnoldarts.de.
For more options, visit https://groups.google.com/d/optout.



--
    R.

Richard Brockie

Real-time bicycle race results - www.ontheday.net

Collin Anderson

unread,
Dec 1, 2014, 1:09:51 PM12/1/14
to django...@googlegroups.com, ric...@ontheday.net
Hi,

Yes, decorators are just fancy syntax. These two code blocks are the same:

@the_decorator
def the_view(*args):
   
# etc

def the_view(*args):
   
# etc
the_view
= the_decorator(the_view)

Collin
Reply all
Reply to author
Forward
0 new messages