Hi Iago

Thanks for writing to the list.

The proposal feels like complicating the decorator too much to me. If you
simplify the logic for the redirect for your particular use case, you can
implement your own decorator in a handful of lines. I think that’s
sufficient.

Adam

On Fri, 19 Nov 2021 at 10:40, Iago González Rodríguez <igo...@gmail.com>
wrote:

> Hi everyone, this is my first proposal so please don't be too hard on me :)
>
> *Context:*
> I was implementing one of my first websites using Django, and when I tried
> to add the logic for restricting access of certain views to some users, I
> discovered this `user_passes_test` decorator, which is a pretty awesome
> decorator. But then in my test function I needed to use the Django messages
> framework to send a message when the user cannot access the view, but I
> realized that `user_passes_test` only sends the user object, and there is
> no option to pass the request object.
>
> I searched my problem on the Internet and I found a few related issues:
> 1) How to pass Django request object in user_passes_test... -
> Stackoverflow
> <https://stackoverflow.com/questions/11872560/how-to-pass-django-request-object-in-user-passes-test-decorator-callable-functio>
> 2) Show error message when decorator fails - Stackoverflow
> <https://stackoverflow.com/questions/16375023/show-error-message-when-decorator-fails>
> And I didn't search more because I understood that there is only one
> solution right now: overwrite the `user_passes_test` function.
>
> *Proposal*
> This is a pretty old problem (first issue is 9 years old) and it seems
> that every so often a new user runs into this problem, the solution of
> which is inelegant (overwrite the code of the Django function).
>
> I know that the workaround is very simple, and that seems to be the reason
> why no one has decided to bother to modify the logic of that function. But
> if the solution is so simple (and also does not change the current behavior
> of Django), why not implement it in the Django source code instead of
> forcing developers to implement a workaround in their project?
>
> Then I opened a ticket in the Django issue tracker
> <https://code.djangoproject.com/ticket/33299>, but sadly it was rejected
> (maybe I didn't explain correctly the problem, or it seemed like it
> wasn't worth the effort).
>
> *Final solution*
> Since I was rejected, I did some simple tests (link to online-python.com)
> <https://www.online-python.com/swnTmgrp6c> to try out if my solution
> would work (it was my first time working with this kind of advanced
> decorators). Then I improved the solution sent and the final result is this
> (contrib/auth/decorators.py
> <https://raw.githubusercontent.com/django/django/ca9872905559026af82000e46cde6f7dedc897b6/django/contrib/auth/decorators.py>
> ):
>
> def request_passes_test(test_func, login_url=None,
> redirect_field_name=REDIRECT_FIELD_NAME, attrname=None):
>     """
>     Decorator for views that checks that the request passes the given test,
>     redirecting to the log-in page if necessary. The test should be a
> callable
>     that takes the request object and returns True if the request passes.
>     Optionally you can pass an attribute name in order to test an attribute
>     from request.
>     """
>     def decorator(view_func):
>         @wraps(view_func)
>         def _wrapped_view(request, *args, **kwargs):
>             attr = request if attrname is None else getattr(request,
> attrname)
>             if test_func(attr):
>                 return view_func(request, *args, **kwargs)
>             path = request.build_absolute_uri()
>             resolved_login_url = resolve_url(login_url or
> settings.LOGIN_URL)
>             # If the login url is the same scheme and net location then
> just
>             # use the path as the "next" url.
>             login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
>             current_scheme, current_netloc = urlparse(path)[:2]
>             if ((not login_scheme or login_scheme == current_scheme) and
>                     (not login_netloc or login_netloc == current_netloc)):
>                 path = request.get_full_path()
>             from django.contrib.auth.views import redirect_to_login
>             return redirect_to_login(
>                 path, resolved_login_url, redirect_field_name)
>         return _wrapped_view
>     return decorator
>
>
> def user_passes_test(test_func, login_url=None,
> redirect_field_name=REDIRECT_FIELD_NAME):
>     """
>     Decorator for views that checks that the user passes the given test,
>     redirecting to the log-in page if necessary. The test should be a
> callable
>     that takes the user object and returns True if the user passes.
>     """
>     return request_passes_test(test_func, login_url, redirect_field_name,
> attrname="user")
>
> With this solution the `user_passes_test` decorator would be working as
> it is working right now, but we could use `request_passes_test` in order
> to do more advanced stuff in our test functions, such as using the Django
> messages framework in the test function, or checking other parameters of
> the `request` object.
>
> Thank you very much for your time, and please ask me for more information
> if you have questions. I am willing to open the Pull Request myself, and
> add modifications to the solution if needed. It would be awesome to join
> the team of Django contributors :D
>
> Best regards,
> Iago.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Django developers (Contributions to Django itself)" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-developers+unsubscr...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-developers/564e0f9c-886d-4c73-9397-28adb02b5d5dn%40googlegroups.com
> <https://groups.google.com/d/msgid/django-developers/564e0f9c-886d-4c73-9397-28adb02b5d5dn%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/CAMyDDM1bmVYpB15PyK7hxXaEETnePfWOkP55qjqMuEuf3zaW4w%40mail.gmail.com.
  • New... Iago González Rodríguez
    • ... 'Adam Johnson' via Django developers (Contributions to Django itself)
      • ... Iago González Rodríguez

Reply via email to