Ticket #5394: redirect_to_fieldaddition.diff

File redirect_to_fieldaddition.diff, 7.8 KB (added by DavidReynolds, 8 years ago)

All encompassing patch

  • django/contrib/auth/views.py

     
    99from django.contrib.auth import REDIRECT_FIELD_NAME
    1010from django.utils.translation import ugettext as _
    1111
    12 def login(request, template_name='registration/login.html'):
     12def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME):
    1313    "Displays the login form and handles the login action."
    1414    manipulator = AuthenticationForm(request)
    15     redirect_to = request.REQUEST.get(REDIRECT_FIELD_NAME, '')
     15    redirect_to = request.REQUEST.get(redirect_field_name, '')
    1616    if request.POST:
    1717        errors = manipulator.get_validation_errors(request.POST)
    1818        if not errors:
     
    3535
    3636    return render_to_response(template_name, {
    3737        'form': oldforms.FormWrapper(manipulator, request.POST, errors),
    38         REDIRECT_FIELD_NAME: redirect_to,
     38        redirect_field_name: redirect_to,
    3939        'site_name': current_site.name,
    4040    }, context_instance=RequestContext(request))
    4141
     
    5656        login_url = settings.LOGIN_URL
    5757    return logout(request, login_url)
    5858
    59 def redirect_to_login(next, login_url=None):
     59def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    6060    "Redirects the user to the login page, passing the given 'next' page"
    6161    if not login_url:
    6262        from django.conf import settings
    6363        login_url = settings.LOGIN_URL
    64     return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))
     64    return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, next))
    6565
    6666def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html',
    6767        email_template_name='registration/password_reset_email.html'):
  • django/contrib/auth/decorators.py

     
    22from django.http import HttpResponseRedirect
    33from urllib import quote
    44
    5 def user_passes_test(test_func, login_url=None):
     5def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    66    """
    77    Decorator for views that checks that the user passes the given test,
    88    redirecting to the log-in page if necessary. The test should be a callable
     
    1515        def _checklogin(request, *args, **kwargs):
    1616            if test_func(request.user):
    1717                return view_func(request, *args, **kwargs)
    18             return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))
     18            return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, quote(request.get_full_path())))
    1919        _checklogin.__doc__ = view_func.__doc__
    2020        _checklogin.__dict__ = view_func.__dict__
    2121
    2222        return _checklogin
    2323    return _dec
    2424
    25 login_required = user_passes_test(lambda u: u.is_authenticated())
    26 login_required.__doc__ = (
     25def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME):
    2726    """
    2827    Decorator for views that checks that the user is logged in, redirecting
    2928    to the log-in page if necessary.
    3029    """
     30    actual_decorator = user_passes_test(
     31        lambda u: u.is_authenticated(),
     32        redirect_field_name=redirect_field_name
    3133    )
     34    if function:
     35        return actual_decorator(function)
     36    return actual_decorator
    3237
    3338def permission_required(perm, login_url=None):
    3439    """
  • tests/modeltests/test_client/views.py

     
    122122    return HttpResponse(t.render(c))
    123123login_protected_view = login_required(login_protected_view)
    124124
     125def login_protected_view_changed_redirect(request):
     126    "A simple view that is login protected with a custom redirect field set"
     127    t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template')
     128    c = Context({'user': request.user})
     129   
     130    return HttpResponse(t.render(c))
     131login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect)
     132
    125133def session_view(request):
    126134    "A view that modifies the session"
    127135    request.session['tobacconist'] = 'hovercraft'
  • tests/modeltests/test_client/models.py

     
    250250        self.assertEqual(response.status_code, 200)
    251251        self.assertEqual(response.context['user'].username, 'testclient')
    252252
     253    def test_view_with_login_and_custom_redirect(self):
     254        "Request a page that is protected with @login_required(redirect_field_name='redirect_to')"
     255       
     256        # Get the page without logging in. Should result in 302.
     257        response = self.client.get('/test_client/login_protected_view_custom_redirect/')
     258        self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/')
     259
     260        # Log in
     261        login = self.client.login(username='testclient', password='password')
     262        self.failUnless(login, 'Could not log in')
     263
     264        # Request a page that requires a login
     265        response = self.client.get('/test_client/login_protected_view_custom_redirect/')
     266        self.assertEqual(response.status_code, 200)
     267        self.assertEqual(response.context['user'].username, 'testclient')
     268
    253269    def test_view_with_bad_login(self):
    254270        "Request a page that is protected with @login, but use bad credentials"
    255271
  • tests/modeltests/test_client/urls.py

     
    1313    (r'^form_view/$', views.form_view),
    1414    (r'^form_view_with_template/$', views.form_view_with_template),
    1515    (r'^login_protected_view/$', views.login_protected_view),
     16    (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
    1617    (r'^session_view/$', views.session_view),
    1718    (r'^broken_view/$', views.broken_view),
    1819    (r'^mail_sending_view/$', views.mail_sending_view),
  • docs/authentication.txt

     
    402402    def my_view(request):
    403403        # ...
    404404
     405``login_required`` also takes an optional ``redirect_field_name`` parameter. Example::
     406   
     407    from django.contrib.auth.decorators import login_required
     408
     409    def my_view(request):
     410        # ...
     411    my_view = login_required(redirect_field_name='redirect_to')(my_view)
     412
     413Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4::
     414   
     415    from django.contrib.auth.decorators import login_required
     416
     417    @login_required(redirect_field_name='redirect_to')
     418    def my_view(request):
     419        # ...
     420
    405421``login_required`` does the following:
    406422
    407423    * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
    408424      (``/accounts/login/`` by default), passing the current absolute URL
    409       in the query string as ``next``. For example:
     425      in the query string as ``next`` or the value of ``redirect_field_name``.
     426      For example:
    410427      ``/accounts/login/?next=/polls/3/``.
    411428    * If the user is logged in, execute the view normally. The view code is
    412429      free to assume the user is logged in.
Back to Top