Django写一个装饰器:从首页点击详情页,如已登录,进详情页;如未登录,跳转至登录页面,登录成功后,跳转至详情页

有的网站需求,如果用户未登录,能够进入首页,但当点击想要进入详情页的时候,就会跳转到登录页面,登录完成之后,有的需求需要进入首页;有的需要进入点击登录之前你的意向页面
第一种:登录之后,进入首页。
第二种:登录之后,进入登录之前你点击想进入的意向页面

那么,对于第一种,登录之后,进入首页。Django有一种自带装饰器。比较简单,下面讲解:
在views.py中:
一、如果是普通视图函数:则使用login_required

from django.contrib.auth.views import login_required

@login_required
def add(request):
    if request.method == 'GET':
        return render(request, './subject/add.html')
    elif request.method == 'POST':
        try:
            name = request.POST.get('name')
            amount = request.POST.get('amount')
            days = request.POST.get('days')
            number = request.POST.get('number')
            assurance = request.POST.get('assurance')
            remark = request.POST.get('remark')
            s = SubjectModel(name=name,amount=amount,days=days,number=number,assurance = assurance,remark=remark,creater_id=request.user.id,updater_id=request.user.id)
            s.save()
            return redirect('/subject/list')
        except:
            return render(request,'./subject/add.html',{'result':'学科添加失败!请仔细检查'})

二、如果是通用视图函数,使用method_decorator

from django.utils.decorators import method_decorator

class SubjectAddView(View):
    """
    该通用视图是用来展示添加学科的页面subject/add.html,以及处理学科的添加逻辑。
    """
    @method_decorator(login_required)
    def get(self, request):
        return render(request, 'subject/add.html')

    @method_decorator(login_required)
    def post(self, request):
        subject = Subject()
        subject.name = request.POST.get('name')
        subject.amount = request.POST.get('amount')
        subject.days = request.POST.get('days')
        subject.number = request.POST.get('number')

        # 保存学科之前,先判断学科是否已经存在。
        result = Subject.objects.filter(name=subject.name)
        if result:
            error = {'code': '该学科已存在!'}
            # 数据库已经存在该名称的学科
            return render(request, 'subject/add.html', locals())
        # 保存成功,切换Url,进入/subject/index/首页,展示所添加的学科信息。

        # 给学科添加创建人和更新人对应的用户。默认都是当前登录用户。
        subject.creater = request.user
        subject.updater = request.user

        subject.save()
        return redirect(reverse('subject_index'))

上面是通用视图函数和普通视图函数的使用装饰器不同,但是有一点,必须要在settings.py中设置:
添加下面一句话:就是制定被装饰函数,如果没用户登录,所要跳转的网址。在这里就是跳转到登录页面

LOGIN_URL = '/user/login/'

下面,讲解第二种,登录之后,进入登录之前你点击想进入的意向页面
这个都需要进行自定义装饰器了,因为在用户没登录的情况下,你要点击首页上的某一个链接进入详情页。要点击的链接都不一样,也就是意向页面不一样。登录之后,要去意向页面。

思路:在首页的时候,你点击某一个链接,想要进入详情页。一、如果用户已登录,直接进入意向页面。二、1.如果没有用户登录,需要自动跳转至登录页面 2.在跳转至登录页面之前,需要将用户所点击的意向页面url地址,保存在cookie中记录下来 3.跳转至登录页面之后,如果用户登录成功,那么就会从cookie取出,在第2步保存到cookie中的意向url地址,进行重定向即可。

在detail的函数中:

def detail(request,article_id):
    article = Article.objects.get(id=article_id)
    comment_form = CommentForm()
    comments = article.comment_set.all()
    return render(request,'article_page.html',locals())

在登录login的函数中:

def login_func(request):
    if request.method == 'GET':
        return render(request,'login.html')
    elif request.method == 'POST':
        login_form = LoginForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data['username']
            password = login_form.cleaned_data['password']
            user= NewUser.objects.filter(uname=username,upwd=password)
            if user:
                # 允许登录,保存登录的session信息
                request.session['uname'] = username
                # 重定向:需要区分用户直接点击的登录页面进行的登录,还是由其他的页面跳转过来的。
                # 如果用户直接访问的是登录页面,那么直接跳转到首页。
                # 如果是从其他页面跳转过来的,需要获取用户所点击的url地址。比如:用户点击文章标题之后跳转的;用户点击评论之后跳转的;登录之后直接重定向到用户点击的url地址。
                user_click_url = request.COOKIES.get('click_url','')
                if not user_click_url:
                    # 说明是用户直接访问的就是登录页面
                    return redirect(reverse('blog_index'))
                else:
                    # 说明是点击其他链接,跳转过来的。
                    return redirect(user_click_url)
            else:
                return render(request,'login.html',{'error':'用户名和密码错误'})

下面,写装饰器:

from django.http import HttpResponseRedirect

def islogin(func_name):
    def wrapper(request,*args,**kwargs):
        if request.session.get('uname',''):
            # 说明当前处于登录状态,直接调用func_name即可
            return func_name(request,*args,**kwargs)
        else:
            # 此时需要获取用户所点击的url,并保存到cookie当中,再跳转到登录页面。
            response = HttpResponseRedirect('/blog/login/')
            # 用户点击链接,会发送GET请求,对应的request对象中,含有要请求的url地址、请求参数,等等
            response.set_cookie('click_url',request.path)
            return response
    return wrapper

之后,只需要在detail的函数的上面,加上封装好的装饰器即可。
在这里插入图片描述

当跳转至登录页面的时候,会看到浏览器中cookie会有保存的click_url的字段
在这里插入图片描述

其中,有两个小知识点:
一、进行重定向的时候,
如果url路径中有参数,r’^detail/(?P<article_id>\d+)/$’,如何使用reverse()来反射这个带参数的地址?
下面是解决方案:

return redirect(reverse('blog_detail',args=(article_id,)))

如果url路径中没有参数,但是含有?article_id=1这种请求的参数,如何使用reverse()来反射这个url
下面是解决方案

return redirect(reverse('article'+'?article_id='+article_id))

二、装饰器中使用request.path
用户点击链接,会发送GET请求,对应的request对象中,含有要请求的url地址、请求参数,等等
一、如果url路径中有参数:例如localhost:8000/blog/detail/1/
是在request.path中可以获取,发送请求的网址

二、如果url路径中没有参数,但是含有?article_id=1这种请求的参数。例如:localhost:8000/blog/?article_id=1/ 是在request.get_full_path()中可以获取,发送请求的网址。要不然,使用request.path只会获取到?之前的网站,获取不是完整的

猜你喜欢

转载自blog.csdn.net/zhangmengran/article/details/84034951