python3.8 + django==3.1.2
想要实现的功能:从订单页面/order/进入操作,但是处于未登录状态下的话,就要先跳转到登录页面,(重点:)登录成功后,自动重定向回到order页面。
BUG:视图中,登录装饰器,登录功能逻辑均没有问题,但是每次从order页进入登录,登录成功后,没有回到order,而是一直定向到首页。
解决过程:
一直纠结于是否是登录认证装饰器和登录功能中:
path = request.get_full_path()
print('log_auth_backUrl:',path)
return redirect(f'/login/?backUrl={path}')
传入GET的k、v写错了,反复试验排查,都没有写错,当然最好这里都是复制黏贴了。
之后又查看了login视图中的GET是否没取到,分别在验证前后打印:
if request.method == 'POST':
path = request.GET.get('backUrl')
print(request.META)
# path = request.META.get('HTTP_REFERER').split('?backUrl=')[-1]
form = LoginCheck(request.POST)
if form.is_valid():
print('log_get_backUrl:',path)
GET方法无论如何都是空,怎么都取不到当前地址栏中的数据,但是换成从META中取,此时的请求头中的数据还没有经过视图,从META中切分到了想要的地址,视图路由都没有问题,那么就还有一个地方,是模板中地址相关处可能存在问题
视图函数login中,如果是post请求就校验,否则就返回登录页面的代码写在最下方,事实上,这一段最先执行,因为先传来的是GET请求:
form = LoginCheck()
return render(request, 'login.html', {'form': form})
此处是跳转到登录页,让用户填写用户名密码进行登录校验,问题就在提交登录信息的POST请求发回来的时候!!!!
原先错误(2中的样子)代码:
form表单中的action地址是写死了的,那么不管从地址栏中切回任何数据,它都返回到 /login/ ,那么重定向的时候,浏览器自然认为就是从login这个地址开始的而不是/order/,所以总是取不到重定向/order/的地址!!
最终正确版本:
视图层
from django.shortcuts import render,HttpResponse,redirect,reverse
# Create your views here.
from app01.reg_log_forms import RegForm
def index(request):
return render(request,'index.html')
def register(request):
if request.method == 'GET':
form = RegForm()
return render(request,'register.html',{'form':form})
else:
form = RegForm(request.POST)
if form.is_valid():
print('reg_cleaned_data:',form.cleaned_data)
# 注册后跳转登录
login_url = reverse('login')
return redirect(login_url)
else:
err = form.errors.get('__all__')
return render(request,'register.html',{'err':err})
# 登录认证装饰器
def log_auth(func):
def inner(request,*args,**kwargs):
# session校验
name = request.session.get('name')
password = request.session.get('password')
if name and password:
res = func(request,*args,**kwargs)
return res
else:
path = request.get_full_path()
print('log_auth_backUrl:',path)
return redirect(f'/login/?backUrl={path}')
return inner
# 登录,发送session
from app01.reg_log_forms import LoginCheck
def login(request):
if request.method == 'POST':
path = request.GET.get('backUrl')
print(request.META)
# path = request.META.get('HTTP_REFERER').split('?backUrl=')[-1]
form = LoginCheck(request.POST)
if form.is_valid():
print('log_get_backUrl:',path)
print('登录校验通过',form.cleaned_data)
name = form.cleaned_data.get('name')
password = form.cleaned_data.get('password')
request.session['name'] = name
request.session['password'] = password
if path:
obj = redirect(path)
else:
obj = redirect('index')
return obj
else:
return render(request,'login.html',{'form':form})
form = LoginCheck()
return render(request, 'login.html', {'form': form})
@log_auth
def order(request):
return render(request,'order.html')
from django.views import View
from django.utils.decorators import method_decorator
# @method_decorator(log_auth,name='get')
class UserInfo(View):
@method_decorator(log_auth)
def get(self,request):
return render(request,'userinfo.html')
# 退出登录
def logout(request):
request.session.delete()
return redirect('login')
模板层
{% for log_inp in form %}
{{ log_inp.label }}
{{ log_inp }}
{{ log_inp.errors }}
{% endfor %}
小结:模板页面中,如果表单就是提交到当前地址,就干脆不要写了