• Django的具体操作(二)


    今日内容:用户登录以及分页的实现

    views.py

    # 登录动作
    def login_action(request):   # 必须继承request
        if request.method == 'POST':
            username = request.POST.get(username, '')
            password = request.POST.get('password, '')
                if username == 'admin and password == 'admin123456':
                    response = HttpResponseRdirect('/menssage/')
                    response.set_cookie('user', username, 3600) # 添加浏览器cookies
                    return response
    
                elsereturn render(request,'index.html', {'error': '用户名或者密码错误'})

    大家第一下想到的都是这样子的操作。用户登陆成功之后呢,在跳转到视图函数的过程中,通过set_cookie()的方法向浏览器中添加cookie的信息。

    在这里,set_cookie()的方法在里面穿了三个参数,第一个参数user用于表示写入浏览器cookie名字,第二个参数username是由用户在登录页上输入的用户名,就是那个admin

    第三个参数3600,用于设置cookie信息在浏览器里面的保存时间,默认单位为秒。

    在cookie使用中虽然感觉良好,但是会存在一些安全隐患,而session相对而言就更加是安全些,那如何使用session替代cookie呢?

    # 登录动作
    def login_action(request):   # 必须继承request
        if request.method == 'POST':
            username = request.POST.get(username, '')
            password = request.POST.get('password, '')
                if username == 'admin and password == 'admin123456':
                    response = HttpResponseRdirect('/menssage/')
                    response.set_cookie('user', username, 3600) # 添加浏览器cookies
                    request.session['user'] = username # 将信息记录到浏览器
                    return response
    
                elsereturn render(request,'index.html', {'error': '用户名或者密码错误'})       
    
    
        def message(request):
            # username = request.COOKIES.get('user', '')# 读取浏览器cookie
            username = request.session.get('user', '')  # 读取浏览器的session
            return render(request, 'message.html', {'user', username})

    在这里要注意,再次尝试登陆就会报错,为什么,因为django,还没有生成django_session表,只需要再次python manage.py migrate即可!

    但是这样写出来始终很Low!

    其实在django中,已经封装好了用户认证和登陆的相关办法。使用即可。

    from django.contrib import auth
    
    def login_action(request):
        if request.method == 'POST':
            username = request.POST.get('username', '')
            password = request.POST.get('password', '')
            user = auth.authenticate(username=username, password=password) # 必须要写成=的形式
            if user is not None:
                auth.login(request, user) # 登陆
                request.session['user'] = username # 将session记录到浏览器
                response = HttpResponseRedirect('/message/')
                return response
            else:
                return render(request, 'index.html')

    在使用authenticate()函数认证给出的用户名和密码,当用户名和密码都正确则返回一个user对象,否则返回为None

    接下来只要在需要登陆才能访问的视图函数前面添加@login_required即可。

    小细节。在urls中添加新的路径url(r'^accounts/login/$', views.index)

    _____________________________________________________________________________________________

    django 的分页功能:

    django本身是自带分页的

    django提供了Paginator的类来实现分页的功能。

    from django.shortcuts import render
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    
    L = []
    for i in range(999):
        L.append(i)
    
    def index(request):
        current_page = request.GET.get('p')
    
        paginator = Paginator(L, 10)
        # per_page: 每页显示条目数量
        # count:    数据总个数
        # num_pages:总页数
        # page_range:总页数的索引范围,如: (1,10),(1,200)
        # page:     page对象
        try:
            posts = paginator.page(current_page)
            # has_next              是否有下一页
            # next_page_number      下一页页码
            # has_previous          是否有上一页
            # previous_page_number  上一页页码
            # object_list           分页之后的数据列表
            # number                当前页
            # paginator             paginator对象
        except PageNotAnInteger:  # 防止输入不是页码
            posts = paginator.page(1)
        except EmptyPage:  # 防止输入页码超出范围
            posts = paginator.page(paginator.num_pages)
        return render(request, 'index.html', {'posts': posts})

    在HTML页面里

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <ul>
        {% for item in posts %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
    
    <div class="pagination">
          <span class="step-links">
            {% if posts.has_previous %} # 判断是否有上一页
                <a href="?p={{ posts.previous_page_number }}">Previous</a>
            {% endif %}
              <span class="current">
                Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
              </span>
              {% if posts.has_next %} # 判断是否有下一页
                  <a href="?p={{ posts.next_page_number }}">Next</a>
              {% endif %}
          </span>
    
    </div>
    </body>
    </html>

    但要注意的一点是,在django中自带的分页是简单,但是也是有缺点的,当数据量相当大的时候,页面便会排满各式各样的页码图标。所以接下来,我们自己写一个分页

    class Pagination(object):
        """
        自定义分页
        """
        def __init__(self,current_page,total_count,base_url,params,per_page_count=10,max_pager_count=11):
            try:
                current_page = int(current_page)
            except Exception as e:
                current_page = 1
            if current_page <=0:
                current_page = 1
            self.current_page = current_page
            # 数据总条数
            self.total_count = total_count
    
            # 每页显示10条数据
            self.per_page_count = per_page_count
    
            # 页面上应该显示的最大页码
            max_page_num, div = divmod(total_count, per_page_count) # divmod(10,2),结果是(5,0);divmod(11,2),结果是(5,1)
            if div:
                max_page_num += 1
            self.max_page_num = max_page_num
    
            # 页面上默认显示11个页码(当前页在中间)
            self.max_pager_count = max_pager_count
            self.half_max_pager_count = int((max_pager_count - 1) / 2)
    
            # URL前缀
            self.base_url = base_url
    
            # request.GET
            import copy
            params = copy.deepcopy(params)
            params._mutable = True
            # 包含当前列表页面所有的搜索条件
            # {source:[2,], status:[2], gender:[2],consultant:[1],page:[1]}
            # self.params[page] = 8
            # self.params.urlencode()
            # source=2&status=2&gender=2&consultant=1&page=8
            # href="/hosts/?source=2&status=2&gender=2&consultant=1&page=8"
            # href="%s?%s" %(self.base_url,self.params.urlencode())
            self.params = params
    
        @property
        def start(self):
            return (self.current_page - 1) * self.per_page_count
    
        @property
        def end(self):
            return self.current_page * self.per_page_count
    
        def page_html(self):
            # 如果总页数 <= 11
            if self.max_page_num <= self.max_pager_count:
                pager_start = 1
                pager_end = self.max_page_num
            # 如果总页数 > 11
            else:
                # 如果当前页 <= 5
                if self.current_page <= self.half_max_pager_count:
                    pager_start = 1
                    pager_end = self.max_pager_count
                else:
                    # 当前页 + 5 > 总页码
                    if (self.current_page + self.half_max_pager_count) > self.max_page_num:
                        pager_end = self.max_page_num
                        pager_start = self.max_page_num - self.max_pager_count + 1   #倒这数11个
                    else:
                        pager_start = self.current_page - self.half_max_pager_count
                        pager_end = self.current_page + self.half_max_pager_count
    
            page_html_list = []
            # {source:[2,], status:[2], gender:[2],consultant:[1],page:[1]}
            # 首页
            self.params['page'] = 1
            first_page = '<li><a href="%s?%s">首页</a></li>' % (self.base_url,self.params.urlencode(),)
            page_html_list.append(first_page)
    
            # 上一页
            self.params["page"] = self.current_page - 1
            if self.params["page"] < 1:
                pervious_page = '<li class="disabled"><a href="%s?%s" aria-label="Previous">上一页</span></a></li>' % (
                self.base_url, self.params.urlencode())
            else:
                pervious_page = '<li><a href = "%s?%s" aria-label = "Previous" >上一页</span></a></li>' % (
                self.base_url, self.params.urlencode())
            page_html_list.append(pervious_page)
    
            # 中间页码
            for i in range(pager_start, pager_end + 1):
                self.params['page'] = i
                if i == self.current_page:
                    temp = '<li class="active"><a href="%s?%s">%s</a></li>' % (self.base_url,self.params.urlencode(), i,)
                else:
                    temp = '<li><a href="%s?%s">%s</a></li>' % (self.base_url,self.params.urlencode(), i,)
                page_html_list.append(temp)
    
            # 下一页
            self.params["page"] = self.current_page + 1
            if self.params["page"] > self.max_page_num:
                self.params["page"] = self.current_page
                next_page = '<li class="disabled"><a href = "%s?%s" aria-label = "Next">下一页</span></a></li >' % (
                self.base_url, self.params.urlencode())
            else:
                next_page = '<li><a href = "%s?%s" aria-label = "Next">下一页</span></a></li>' % (
                self.base_url, self.params.urlencode())
            page_html_list.append(next_page)
    
            # 尾页
            self.params['page'] = self.max_page_num
            last_page = '<li><a href="%s?%s">尾页</a></li>' % (self.base_url, self.params.urlencode(),)
            page_html_list.append(last_page)
    
            return ''.join(page_html_list)
    没有过不去的坎,只有没加够的油!
  • 相关阅读:
    JavaScript实现继承机制(4)——构造函数+原型链混合方式
    NodeJS”热部署“代码,实现动态调试
    初识NodeJS,一个基于GoogleV8引擎的Javascript运行环境
    那些你不得不知道的JavaScript 变量命名规则
    JavaScript声明全局变量的三种方式
    JavaScript实现继承机制(3)——通过原型链(prototype chaining)方式
    JavaScript实现继承机制(1)—— 构造函数方法对象冒充
    C# readonly和const
    C# winform增加界面动态加载的流畅性
    C# 正确操作字符串,规避字符串转换所带来的额外开销
  • 原文地址:https://www.cnblogs.com/zhoulixiansen/p/9153036.html
Copyright © 2020-2023  润新知