J'ai une page de connexion qui fonctionne bien à l'exception de la redirection vers la page de référence. L'utilisateur reçoit un email avec un lien direct au sein de l'application, ils (dans cet exemple) ne sont pas déjà connectés et sont redirigés vers la page de connexion. Une fois la connexion établie, l’utilisateur est redirigé vers un chemin codé en dur. Voir exemple ci-dessous.
URL dans l'email: http://localhost:8000/issueapp/1628/view/22
URL de la page de connexion: http://localhost:8000/login?next=/issueapp/1628/view/22
Vue de connexion (avec redirection codée en dur):
def login_user(request):
state = "Please log in below..."
username = password = ''
if request.POST:
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
return HttpResponseRedirect('/issueapp/1628/')
else:
state = "Your account is not active, please contact the site admin."
else:
state = "Your username and/or password were incorrect."
return render_to_response(
'account_login.html',
{
'state':state,
'username': username
},
context_instance=RequestContext(request)
)
Vue de connexion (avec la redirection "suivante"):
def login_user(request):
state = "Please log in below..."
username = password = ''
if request.POST:
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
return HttpResponseRedirect(request.GET['next'])
else:
state = "Your account is not active, please contact the site admin."
else:
state = "Your username and/or password were incorrect."
return render_to_response(
'account_login.html',
{
'state':state,
'username': username
},
context_instance=RequestContext(request)
)
La vue ci-dessus donne lieu à une exception "Key 'next' not found in <QueryDict: {}>"
Le formulaire ne semble pas publier la variable "next", même si elle figure dans l'URL et dans le formulaire. J'ai cherché et cherché partout et je ne peux pas comprendre pourquoi cela ne fonctionne pas. Des idées?
Référence additionnelle:
Modèle de connexion:
{% block content %}
{{ state }}
<form action="/login/" method="post" >
{% csrf_token %}
{% if next %}
<input type="hidden" name="next" value="{{ next }}" />
{% endif %}
username:
<input type="text" name="username" value="{{ username }}" /><br />
password:
<input type="password" name="password" value="" /><br />
<input type="submit" value="Log In"/>
{% debug %}
</form>
{% endblock %}
EDIT: Le code ci-dessous est en train de fonctionner pour moi (grâce à l'aide de Paulo Bu)! **
Login View:
def login_user(request):
state = "Please log in below..."
username = password = ''
next = ""
if request.GET:
next = request.GET['next']
if request.POST:
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
state = "You're successfully logged in!"
if next == "":
return HttpResponseRedirect('/issueapp/')
else:
return HttpResponseRedirect(next)
else:
state = "Your account is not active, please contact the site admin."
else:
state = "Your username and/or password were incorrect."
return render_to_response(
'account_login.html',
{
'state':state,
'username': username,
'next':next,
},
context_instance=RequestContext(request)
)
Modèle de connexion:
{{ state }}
{% if next %}
<form action="/login/?next={{next}}" method="post" >
{%else%}
<form action="/login/" method="post" >
{% endif %}
{% csrf_token %}
username:
<input type="text" name="username" value="{{ username }}" /><br />
password:
<input type="password" name="password" value="" /><br />
<input type="submit" value="Log In"/>
{% debug %}
</form>
Votre code est correct, le seul problème est que, sous la forme que vous transmettez à l'attribut next
en tant que publication, car la méthode est post
. Dans les vues, vous essayez d’obtenir le paramètre next
dans le dictionnaire get
, ce qui est évident non présent.
Vous devez déclarer le formulaire HTML action
comme ceci pour que vos vues fonctionnent.
{% if next %}
<form action="/login/?next={{next}}" method="post" >
{%else%}
<form action="/login/" method="post" >
{% endif %}
{% csrf_token %}
username:
<input type="text" name="username" value="{{ username }}" /><br />
password:
<input type="password" name="password" value="" /><br />
<input type="submit" value="Log In"/>
{% debug %}
</form>
Là, s'il existe une variable next
, vous devez inclure dans la url
pour la récupérer en tant que paramètre get. Sinon, le formulaire ne l'inclut pas.
C'est la meilleure approche, mais vous pouvez également résoudre ce problème dans vos vues en demandant la variable next
au dictionnaire POST
comme ceci:
return HttpResponseRedirect(request.POST.get('next'))
Notez que cela ne fonctionnera que si le template account_login
a une variable appelée next
. Vous devez le générer dans les vues et le transmettre au modèle lorsque vous le rendez.
Normalement, dans le modèle, vous feriez quelque chose comme ceci:
# this would be hardcoded
next = '/issueapp/1628/view/22'
# you may add some logic to generate it as you need.
et ensuite vous faites:
return render_to_response(
'account_login.html',
{
'state':state,
'username': username,
'next':next
},
context_instance=RequestContext(request)
)
J'espère que cela t'aides!
Je définirais dans votre vue la fonction next_page = request.GET['next']
, puis je la redirigerais par return HttpResponseRedirect(next_page)
afin que vous n'ayez jamais besoin de changer de modèle Il suffit de définir @login_required
et tout va bien.
L'utilisateur A tente d'accéder - sans être connecté - https: //www.domain.tld/account/ . Django le redirige parce que @login_required
est défini sur le LOGIN_URL
défini dans votre fichier settings.py. La méthode UserLogin
essaie maintenant de GET
le paramètre next
et le redirige si l'utilisateur A se connecte avec succès.
LOGIN_URL = '/login/'
url(r'^account/', account, name='account'),
url(r'^login/$', UserLogin, name='login'),
@login_required
def account(request):
return HttpResponseRedirect("https://www.domain.tld/example-redirect/")
def UserLogin(request):
next_page = request.GET['next']
if request.user.is_authenticated():
return HttpResponseRedirect(next_page)
else:
if request.method == 'POST':
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(email=username, password=password)
if user is not None and user.is_active:
login(request, user)
return HttpResponseRedirect(next_page)
else:
error_msg = 'There was an error!'
return render(request, "login", {'form': form, 'error_msg': error_msg})
else:
error_msg = "There was an error!"
return render(request, "login", {'form':form, 'error_msg':error_msg})
else:
form = UserLoginForm()
return render(request, "login", {'form': form})
Si vous voulez être plus générique, vous pouvez simplement faire quelque chose comme ceci, qui transmet l'un des paramètres GET lors de la publication du formulaire:
<form action="/path-to-whatever/{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" method="post">
Plutôt que d’affecter next
à votre vue et de le transmettre à un modèle, il n’est pas plus pratique d’utiliser ?next={{request.path}}
dans votre modèle. (N'oubliez pas d'activer Django.core.context_processors.request
dans settings.py
, qui est généralement activé par défaut dans Django 1.6)
Voici le lien dit à propos de la même
https://docs.djangoproject.com/fr/1.6/topics/auth/default/#the-raw-way
<form action="/login/?next={{request.path}}" method="post" >
est le code requis.
Remarque:
Vous pouvez aussi obtenir l'URL actuelle avec request.path
à partir de view
.
Merci à buffer . Je viens de copier et coller votre commentaire après l'avoir essayé moi-même dans mon propre code.
Il suffit de mettre
<form action="" method="post" >
Action vide 'what ever current complete url is
'