zoukankan      html  css  js  c++  java
  • django中的auth模块以及分页器

    1.auth模块 

      auth模块是Django提供的标准权限管理系统,可以提供用户身份认证,和权限管理

      auth可以和admin模块配合使用, 快速建立网站的管理系统

      在INSTALLED_APPS中添加'django.contrib.auth'使用该APP, auth模块默认启用

    导入auth模块

    from django.contrib import auth

    1.1 authenticate()   :验证用户输入的用户名和密码是否相同

      提供用户认证,即验证用户名以及密码是否正确,一般需要username  password(django的auth_user自带数据库就有的名字)两个关键字参数

    user = authenticate(username='someone',password='somepassword')

    1.2 auth.login(request,user) :此函数使用django的session框架给某个已认证的用户附加上session id等信息

    设置完成后request.user就是全局的变量了,直接可以随意随时随地的使用request.user进行取值

    auth.login(request,user)  # 直接使用

    1.3 logout(request): 注销用户,无返回值,当前请求的session信息会在数据路中全部清除

    auth.logout(request)

    1.4 user对象的is_authenticated()  登录验证,用户登录后才能访问页面,没有登录则跳转到登录页

    if not request.user.is_authenticated:
        return redirect("/login/")

    对于此,我们也可以使用django提供的组件装饰器:login_required()

    from django.contrib.auth.decorators import login_required
          
    @login_required
    def my_view(request):
      ...

    1.5 创建用户

      在django自带的auth_user中创建用户,注意导入方式

    from django.contrib.auth.models import User
    def register(request):
        User.objects.create(username="luffy",password=123)
        return redirect("/login/")

    1.6 修改密码 set_password()

    user = User.objects.get(username='')
    user.set_password(password='')
    user.save 

    2.演示代码

    url.py

    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path("login/",views.login),
        path("index/",views.index),
        path("logout/",views.logout),
    ]
    

     login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <form action="" method="post">
        {% csrf_token %}
        用户名:<input type="text" name="user">
        密码:<input type="password" name="pwd">
        <input type="submit">
    </form>
    <body>
    
    </body>
    </html>
    

     index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h3>Hi, {{ request.user.username }} <a href="/logout/">注销</a></h3>
    </body>
    </html>
    

     views.py

    登录

    rom django.shortcuts import render,redirect
    
    # 导入用户认证组件,auth模块
    from django.contrib import auth
    
    def login(request):
    	if request.method=="POST":
    		user = request.POST.get("user")
    		pwd = request.POST.get("pwd")
    		# 用户验证,一致则返回user对象,否则返回none
    		user = auth.authenticate(username=user,password=pwd)
    		print(user)
    		if user:
    			# 登录成功,则注册session组件,在session中存储信息
    			auth.login(request,user)
    			return redirect("/index/")
    	return render(request,"login.html")
    

     登录验证

    def index(request):
    	# 打印存储在auth_user中的用户id,及姓名
    	print(request.user.id,request.user.username)
    	# 登录验证,用户登录后才能访问某些页面,没有登录就访问该页面则跳转登录页面
    	if not request.user.is_authenticated:
    		return redirect("/login/")
    	return render(request, "index.html")
    

     注销

    def logout(request):
    	# 注销用户,之前请求的session信息会全部清除
    	auth.logout(request)
    	return redirect("/login/")
    

     3. 分页器(paginator)

    3.1 实现方式一( 利用了django自带的paginator分页组件)

     代码:

    models.py

    from django.db import models
    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.DecimalField(max_digits=8,decimal_places=2)

    index.html

    这里导入了bootstrap的样式,里面还有其他分页器的样式,自己可以在官网查找

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.1.0/css/bootstrap.css">
    </head>
    
    <body>
        <h3>INDEX</h3>
        <ul>
            {% for book in book_list %}
            <li>{{ book.title }}>>>>{{ book.price }}</li>
            {% endfor %}
        </ul>
    <nav aria-label="Page navigation">
        <ul class="pagination">
        {% for i in pageRange %}
             {% if current_num == i %}
              <li class="active"><a href="?page={{ i }}">{{ i }}</a></li>
             {% else %}
              <li><a href="?page={{ i }}">{{ i }}</a></li>
             {% endif %}
        {% endfor %}
        </ul>
    </nav>
    </body>
    </html>

    views.py

    from django.shortcuts import render
    
    from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
    from app01.models import Book
    
    def index(request):
    	# 批量导入
    	book_list = []
    	for i in range(1,101):
    		book = Book(title="book_%s" % i,price=i**2)
    		book_list.append(book)
    	# 批量创建列表中的对象,这样效率比硬编码创建要高得多
    	Book.objects.bulk_create(book_list)
    
    	# 分页器
    	paginator = Paginator(book_list,10)    # 必须的先实例化
    	print(paginator.count)  # 总数据量
    	print(paginator.num_pages)  # 分页数
    	print(paginator.page_range)     #页码范围,range(1, 11)
    
    	page1 = paginator.page(1)    # 第一页的page对象
    	print(page1.start_index())   # 起始页码,1
    	print(page1.end_index())     # 最的页码数,10
    	print(page1.has_next())      # True
    	print(page1.has_other_pages())    # True
    	print(page1.has_previous())      # False
    	print(page1.next_page_number())    # 2
    	# print(page1.previous_page_number())  # 报错,没有前一页
    	print(page1.object_list)     # 第一页的所有数据,不过得到的是对象
    
    	# 报错
    	# page = paginator.page(12)   # error:EmptyPage
    	# page = paginator.page("z")    # error:PageNotAnInteger
            return render(request, "index.html", locals())
    

    基于以上案例对分页器样式的设计

    	book_list = Book.objects.all()
    	paginator = Paginator(book_list, 2)
    	try:
    		current_num = int(request.GET.get("page", 1))
    		book_list = paginator.page(current_num)
    	except EmptyPage:
    		book_list = paginator.page(1)
    
    	#  如果页数特别多时,换另外一种显示方式
    	if paginator.num_pages > 11:
    
    		if current_num - 5 < 1:
    			pageRange = range(1, 11)
    		elif current_num + 5 > paginator.num_pages:
    			pageRange = range(current_num - 5, paginator.num_pages + 1)
    
    		else:
    			pageRange = range(current_num - 5, current_num + 6)
    
    	else:
    		pageRange = paginator.page_range
    
    	return render(request, "index.html", locals())
    

     最终效果:

    3.2分页器实现方式二(自己编写分页组件)

      这里的效果比上一种更加美观一些,实现原理核心部分封装成了一个类方法,直接放在我们的应用下,在视图中导入即可

    pagination.py

    class Pagination:
        def __init__(self, page_num, total_num, per_page_num=10, max_show=11):
            self.page_num = page_num    # 当前页面数
            self.total_num = total_num  # 总数据量
            self.per_page_num = per_page_num    # 每页显示数据条数
            self.max_show = max_show    # 最多显示页码数
            self.half_show = self.max_show // 2
            self.total_page, more = divmod(total_num, per_page_num)
            if more:
                self.total_page += 1
            if self.page_num > self.total_page:
                self.page_num = self.total_page
            elif self.page_num < 1:
                self.page_num = 1
                
        @property
        def start(self):
            return (self.page_num - 1) * self.per_page_num
    
        @property
        def end(self):
            return self.page_num * self.per_page_num
    
        @property
        def page_html(self):
            page_start = self.page_num - self.half_show
            page_end = self.page_num + self.half_show + 1
            if self.page_num + self.half_show >= self.total_page:
                page_end = self.total_page + 1
                page_start = self.total_page - self.max_show + 1
            if self.page_num <= self.half_show:
                page_start = 1
                page_end = self.max_show + 1
            page_num_list = []
    
            # 添加首页
            page_num_list.append('<li><a href="/user_list/?page={0}">首页</a></li>'.format(1))
            # 添加上一页
            pre_page_num = self.page_num - 1
            if pre_page_num < 1:
                page_num_list.append(
                    '<li class="disabled"><a href="/user_list/?page={0}">上一页</a></li>'.format(pre_page_num))
            else:
                page_num_list.append('<li><a href="/user_list/?page={0}">上一页</a></li>'.format(pre_page_num))
    
            for i in range(page_start, page_end):
                if i == self.page_num:
                    page_num_list.append('<li class="active"><a href="/user_list/?page={0}">{0}</a></li>'.format(i))
                else:
                    page_num_list.append('<li><a href="/user_list/?page={0}">{0}</a></li>'.format(i))
            # 添加下一页
            next_page_num = self.page_num + 1
            if next_page_num > self.total_page:
                page_num_list.append(
                    '<li class="disabled"><a href="/user_list/?page={0}">下一页</a></li>'.format(next_page_num))
            else:
                page_num_list.append('<li><a href="/user_list/?page={0}">下一页</a></li>'.format(next_page_num))
    
            # 添加尾页
            page_num_list.append('<li><a href="/user_list/?page={0}">尾页</a></li>'.format(self.total_page))
    
            page_html = ''.join(page_num_list)
    
            return page_html

    url.py

    from django.contrib import admin
    from django.urls import path,re_path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path('user_list/',views.user_list)
    ]

    views.py

    from django.shortcuts import render
    
    data = []
    for i in range(1, 302):
        data.append({'name': '%s只羊' % i, 'age': '%s只' % i})
    
    def user_list(request):
        from . import pagination    # 从应用中导入我们创建的分页文件
        try:
            page_num = int(request.GET.get('page', 1))   # 这里的get请求是在url上
        except Exception:
            page_num = 1
      # 实例化对象
        page_obj =pagination.Pagination(page_num,len(data))
    
        data1 = data[page_obj.start:page_obj.end]
        return render(request, 'user_list.html', {'user_list': data1, 'page_html': page_obj.page_html})

    user_list.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    </head>
    <body>
    <div class="container">
        <table class="table table-bordered">
            <thead>
            <tr>
                <th>姓名</th>
                <th>只数</th>
            </tr>
            </thead>
            <tbody>
            {% for user in user_list %}
                <tr>
                    <td>{{ user.name }}</td>
                    <td>{{ user.age }}</td>
                </tr>
            {% endfor %}
    
    
            </tbody>
        </table>
    </div>
    
    <div class="text-center">
        <nav aria-label="Page navigation">
            <ul class="pagination">
                {# 加入safe,保证能够从后端将数据传到前端 #}
                {{ page_html|safe }}
            </ul>
        </nav>
    
    </div>
    </body>
    </html>

    最终效果:

     3.3分页器实现方式三(通用类型)  --->出自wusir

    class Pagination(object):
        def __init__(self, current_page, all_count, base_url,query_params, per_page=10, pager_page_count=11):
            """
            分页初始化
            :param current_page: 当前页码
            :param per_page: 每页显示数据条数
            :param all_count: 数据库中总条数
            :param base_url: 基础URL
            :param query_params: QueryDict对象,内部含所有当前URL的原条件
            :param pager_page_count: 页面上最多显示的页码数量
            """
            self.base_url = base_url
            try:
                self.current_page = int(current_page)
                if self.current_page <= 0:
                    raise Exception()
            except Exception as e:
                self.current_page = 1
            self.query_params = query_params
            self.per_page = per_page
            self.all_count = all_count
            self.pager_page_count = pager_page_count
            pager_count, b = divmod(all_count, per_page)
            if b != 0:
                pager_count += 1
            self.pager_count = pager_count
    
            half_pager_page_count = int(pager_page_count / 2)
            self.half_pager_page_count = half_pager_page_count
    
        @property
        def start(self):
            """
            数据获取值起始索引
            :return:
            """
            return (self.current_page - 1) * self.per_page
    
        @property
        def end(self):
            """
            数据获取值结束索引
            :return:
            """
            return self.current_page * self.per_page
    
        def page_html(self):
            """
            生成HTML页码
            :return:
            """
            # 如果数据总页码pager_count<11 pager_page_count
            if self.pager_count < self.pager_page_count:
                pager_start = 1
                pager_end = self.pager_count
            else:
                # 数据页码已经超过11
                # 判断: 如果当前页 <= 5 half_pager_page_count
                if self.current_page <= self.half_pager_page_count:
                    pager_start = 1
                    pager_end = self.pager_page_count
                else:
                    # 如果: 当前页+5 > 总页码
                    if (self.current_page + self.half_pager_page_count) > self.pager_count:
                        pager_end = self.pager_count
                        pager_start = self.pager_count - self.pager_page_count + 1
                    else:
                        pager_start = self.current_page - self.half_pager_page_count
                        pager_end = self.current_page + self.half_pager_page_count
    
            page_list = []
    
            if self.current_page <= 1:
                prev = '<li><a href="#">上一页</a></li>'
            else:
                self.query_params['page'] = self.current_page - 1
                prev = '<li><a href="%s?%s">上一页</a></li>' % (self.base_url,self.query_params.urlencode())
            page_list.append(prev)
            for i in range(pager_start, pager_end + 1):
                self.query_params['page'] = i
                if self.current_page == i:
                    tpl = '<li class="active"><a href="%s?%s">%s</a></li>' % (
                        self.base_url, self.query_params.urlencode(), i,)
                else:
                    tpl = '<li><a href="%s?%s">%s</a></li>' % (self.base_url, self.query_params.urlencode(), i,)
                page_list.append(tpl)
    
            if self.current_page >= self.pager_count:
                nex = '<li><a href="#">下一页</a></li>'
            else:
                self.query_params['page'] = self.current_page + 1
                nex = '<li><a href="%s?%s">下一页</a></li>' % (self.base_url, self.query_params.urlencode(),)
            page_list.append(nex)
            page_str = "".join(page_list)
            return page_str
  • 相关阅读:
    数据--第53课
    数据--第52课
    数据--第51课
    标准模板库中的优先队列(priority_queue)
    进程的定义
    进程的基本概念
    循环不变式
    插入排序
    模板声明
    标准模板库中的队列(queue)
  • 原文地址:https://www.cnblogs.com/LearningOnline/p/9286386.html
Copyright © 2011-2022 走看看