Paddy Popeye Paddy Popeye - 6 months ago 50
Python Question

Django unable to render logout template

Have the following problem; I am following Django by Example, Antonio Mele.The exercise here, is to set up user login and logout.Using the default contrib.auth views. When the code in the book is used. The logout view is that of the admin page logout; seems to be same issue as described here

django logout redirects me to administration page. Have tried all there no success

I have been working on this problem. My code now works, in that the admin template is no longer rendered. However, I am still unable to use my own logout.html. I can redirect to my own login.html... but not the logout.html.The logging out itself is working. User can log in, and out only this issue with the templates. I now only receive one browser error


The page isn't redirecting properly Iceweasel has detected that the >server is redirecting the request for this address in a way that will >never complete.This problem can sometimes be caused by disabling or >refusing to accept cookies.


checked the cookies can see csrf token is accepted

no traceback available no errors :-(

If I use the code below , all works with one exception. I am redirected at logout to the Django Administration logout template, and not my own logout.html....This is when using coede in the book.... My own modified code, with a seperate logout function also did not work generating a maximum recurson error.Editing the URLS.PY stops the rendering of the admin template. but the modified code seems to have an issue in the urls i.e .....

THIS IS NOT WORKING !!!!!

url(r'^logout/$', 'django.contrib.auth.views.logout',{'next_page': '/account/logout'}, name='logout'),


THIS WORKS PERFECTLY !!!!

url(r'^logout/$', 'django.contrib.auth.views.logout',{'next_page': '/account/login'}, name='logout'),


The code from the book is as follows

FROM BOOK SETTINGS.PY

from django.core.urlresolvers import reverse_lazy

LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
LOGIN_URL = reverse_lazy('login')
LOGOUT_URL = reverse_lazy('logout')


FROM BOOK VIEWS.PY

from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from .forms import LoginForm

@login_required
def dashboard(request):
return render(request, 'account/dashboard.html', {'section': 'dashboard'})


def user_login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'], password=cd['password'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled account')
else:
return HttpResponse('Invalid login')
else:
form = LoginForm()
return render(request, 'account/login.html', {'form': form})


FROM BOOK MAIN URLS.PY

from django.conf.urls import include, url
from django.contrib import admin



urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^account/', include('account.urls')),
]


MYAPP(account) URLS.PY

from django.conf.urls import url
from . import views


urlpatterns = [
# url(r'^login/$', views.user_login, name='login'),
url(r'^$', views.dashboard, name='dashboard'),



# login / logout urls
url(r'^login/$', 'django.contrib.auth.views.login', name='login'),
url(r'^logout/$', 'django.contrib.auth.views.logout', name='logout'),
url(r'^logout-then-login/$', 'django.contrib.auth.views.logout_then_login', name='logout_then_login'),


MY MODIFIFED CODE

I have now include a seperate logout definition in my view's and now also pass a {key:value} pair of {'next_page': '/account/logout'}.

if the logout def is used and mapped in the urls file it generates a maximum recursion error at line logout(request)

def logout(request):
logout(request)
request.session.flush()
request.user = AnonymousUser
# Redirect to a success page.
return HttpResponseRedirect(request,'/account/logout.html',context_instance = RequestContext(request))


without this def the only error generated is

"""
The page isn't redirecting properly

"""Iceweasel has detected that the server is redirecting the request for this address in a way that will never complete.

This problem can sometimes be caused by disabling or refusing to accept cookies.""""


"""
I checked cookies in the browser, and see the csrf_token being accepted

For me the strange thing is that if the code: {'next_page': '/account/logout'} is changed to {'next_page': '/account/login'} everything works perfectly. Have tried all suggestions found, am at a loss any help appreciated ....

MY CODE
VIEWS.PY

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from .forms import LoginForm
from django.contrib.auth.decorators import login_required
from django.template import RequestContext
from django.contrib.auth.models import User


# Create your views here.

@login_required
def dashboard(request):
return render(request, 'account/dashboard.html',{'section': 'dashboard' })




def user_login(request):
cd = None
if request.method=='POST':
form = LoginForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
user = authenticate(username=cd['username'],
password=cd['password'])
if user is not None:
if user.is_active:
login(request, user)
return HttpResponse('Authenticated successfully')
else:
return HttpResponse('Disabled Account')
else:
return HttpResponse('Invalid Login')
else:
form = LoginForm()
return render(request, 'account/login.html',{'form': form},context_instance = RequestContext(request))


def logout(request):
logout(request)
request.session.flush()
request.user = AnonymousUser
# Redirect to a success page.
return HttpResponseRedirect(request,'/account/logout.html',context_instance = RequestContext(request))


MY CODE
account/urls.py

from django.conf.urls import url, patterns
from . import views



urlpatterns = [
# post views
#url(r'^login/$', views.user_login, name='login'),
# login/logout urls
url(r'^$', views.dashboard, name='dashboard'),
url(r'^login/$', 'django.contrib.auth.views.login', name='login'),
url(r'^logout/$', 'django.contrib.auth.views.logout',{'next_page': '/account/logout'}, name='logout'),
url(r'^logout-then-login/$','django.contrib.auth.views.logout_then_login', name='logout_then_login'),

]


MY CODE
MAIN URLS.PY

from django.conf.urls import include, url
from django.contrib import admin


urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^account/', include("account.urls")),
]


MYCODE
SETTINGS.PY

LOGIN_REDIRECT_URL = reverse_lazy('dashboard')
LOGIN_URL = reverse_lazy('login')
LOGOUT_URL = reverse_lazy('logout')

INSTALLED_APPS = (
'account',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',

)

MIDDLEWARE_CLASSES = (
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)


# urlpatterns += patterns('django.contrib.auth.views',
# #url(r'^login/$', 'login', { 'template_name': 'registration/login.html'}, name='login' ),
# #url(r'^logout/$', 'logout', { 'template_name': 'registration/logout.html', 'next_page':reverse('index') }, name='logout' ),
# )


MYCODE

logout.html

{% extends "base1.html" %}

{% block title %}Logged Out{% endblock %}


{% block content %}
<h1>
Logged Out
</h1>
<p>
You have been successfully logged out. You can <a href="{% url "login" %}">Log-in again</a>
</p>{% endblock %}


MYCODE
base1.html

{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{% static 'css/base.css' %}">
</head>
<body>


<div id="header">
<span class="logo">
BookMarks
</span>
{% if user.is_authenticated %}
<ul class="menu">

<li {% if section == "dashboard" %}class="selected"{% endif %}>
<a href="{% url 'dashboard' %}">My dashboard</a>
</li>
<li {% if section == "images" %}class="selected"{% endif %}>
<a href="#">Images</a>
</li>
<li {% if section == "people" %}class="selected"{% endif %}>
<a href="#">People</a>
</li>
</ul>
{% endif %}

{%if user.is_authenticated %}
<span class="user">


Hello {{ user.first_name }} {{ user.last_name }},
<a href="{% url 'logout' %}">Logout</a>

{% else %}
<a href='{% url "login" %}'>Log-in</a>
{% endif %}
</span>
</div>

<div id="content">
{% block content %}
{% endblock %}
</div>

</body>

</html>

Answer

You are using contrib.auth's logout view in your urls.py. This view redirects to the URL specified by 'next_page'. You provide '/account/logout' as next_page -- where again the logout view is called!

That leads to an (infinite) redirect loop: the view redirects to itself.

Try instead: in your own logout view:

# no redirecting here!
return render(request, 'account/logout.html', 
              context_instance=RequestContext(request))

Add a url for that view in account/urls.py:

url(r'^post-logout/$', logout, name='post-logout'), 
# logout being your own view

Then provide that url as 'next_page' to the actual (auth) logout:

url(r'^logout/$', 'django.contrib.auth.views.logout',
    {'next_page': '/account/post-logout'},  name='logout'),