Django组件

Django的分页器(paginator)

demo

视图

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import *
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def index(request):

    '''
    批量导入数据:

    Booklist=[]
    for i in range(100):
        Booklist.append(Book(title="book"+str(i),price=30+i*i))
    Book.objects.bulk_create(Booklist)
    '''

    '''
分页器的使用:

    book_list=Book.objects.all()

    paginator = Paginator(book_list, 10)

    print("count:",paginator.count)           #数据总数
    print("num_pages",paginator.num_pages)    #总页数
    print("page_range",paginator.page_range)  #页码的列表



    page1=paginator.page(1) #第1页的page对象
    for i in page1:         #遍历第1页的所有数据对象
        print(i)

    print(page1.object_list) #第1页的所有数据


    page2=paginator.page(2)

    print(page2.has_next())            #是否有下一页
    print(page2.next_page_number())    #下一页的页码
    print(page2.has_previous())        #是否有上一页
    print(page2.previous_page_number()) #上一页的页码



    # 抛错
    #page=paginator.page(12)   # error:EmptyPage

    #page=paginator.page("z")   # error:PageNotAnInteger

    '''


    book_list=Book.objects.all()

    paginator = Paginator(book_list, 10)
    page = request.GET.get('page',1)
    currentPage=int(page)


    try:
        print(page)
        book_list = paginator.page(page)
    except PageNotAnInteger:
        book_list = paginator.page(1)
    except EmptyPage:
        book_list = paginator.page(paginator.num_pages)


    return render(request,"index.html",{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})
view

模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" 
    integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>

<div class="container">

    <h4>分页器</h4>
    <ul>

        {% for book in book_list %}
             <li>{{ book.title }} -----{{ book.price }}</li>
        {% endfor %}

     </ul>


    <ul class="pagination" id="pager">

                 {% if book_list.has_previous %}
                    <li class="previous"><a href="/index/?page={{ book_list.previous_page_number }}">上一页</a></li>
                 {% else %}
                    <li class="previous disabled"><a href="#">上一页</a></li>
                 {% endif %}


                 {% for num in paginator.page_range %}

                     {% if num == currentPage %}
                       <li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
                     {% else %}
                       <li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>

                     {% endif %}
                 {% endfor %}



                 {% if book_list.has_next %}
                    <li class="next"><a href="/index/?page={{ book_list.next_page_number }}">下一页</a></li>
                 {% else %}
                    <li class="next disabled"><a href="#">下一页</a></li>
                 {% endif %}

            </ul>
</div>



</body>
</html>
html

进阶限制所显示的分页数量

 1 def index(request):
 2 
 3 
 4     book_list=Book.objects.all()
 5 
 6     paginator = Paginator(book_list, 15)
 7     page = request.GET.get('page',1)
 8     currentPage=int(page)
 9 
10     #  如果页数十分多时,换另外一种显示方式
11     if paginator.num_pages>11:
12 
13         if currentPage-5<1:
14             pageRange=range(1,11)
15         elif currentPage+5>paginator.num_pages:
16             pageRange=range(currentPage-5,paginator.num_pages+1)
17 
18         else:
19             pageRange=range(currentPage-5,currentPage+5)
20 
21     else:
22         pageRange=paginator.page_range
23 
24 
25     try:
26         print(page)
27         book_list = paginator.page(page)
28     except PageNotAnInteger:
29         book_list = paginator.page(1)
30     except EmptyPage:
31         book_list = paginator.page(paginator.num_pages)
32 
33 
34     return render(request,"index.html",locals())
more

自定义分页

自定义分页组件

import copy
"""
自定义分页
"""


class Pagination(object):

    def __init__(self, current_page_num, all_count, request, per_page_num=10, max_page_num=11):
        """
        封装分页相关数据
        :param current_page_num: 当前页码
        :param all_count: 数据总数
        :param per_page_num: 每页显示的数据条数
        :param max_page_num: 最大显示的页数
        """

        # 捕捉异常页码,异常则显示第一页
        try:
            current_page_num = int(current_page_num)
        except Exception as e:
            current_page_num = 1

        if current_page_num < 1:
            current_page_num = 1
        if current_page_num > all_count/per_page_num:
            all_pager, tmp = divmod(all_count, per_page_num)
            if tmp:
                current_page_num = all_pager+1
            else:
                current_page_num = all_pager

        self.current_page_num = current_page_num
        self.all_count = all_count
        self.per_page_num = per_page_num
        self.max_page_num = max_page_num

        # 计算总页数
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        # 计算最多显示页数的一半,为了页数过多时,只实现一定的数量的实现做准备
        self.max_page_num_half = int((max_page_num-1)/2)

        # 保存搜索条件 获取{"a":"1","b":"2"}
        self.params = copy.deepcopy(request.GET)

    # 计算当前页所显示数据的起始索引
    @property
    def start(self):
        return (self.current_page_num - 1)*self.per_page_num

    # 计算当前页所显示数据的结束索引
    @property
    def end(self):
        return self.current_page_num * self.per_page_num

    # 自定义分页的逻辑函数
    def page_html(self):
        # 总页码数 < 最大显示页码数,即全部显示
        if self.all_pager < self.max_page_num:
            page_start = 1
            page_end = self.all_pager + 1

        # 总页码数 > 最大显示页码数,即显示最大页码数
        else:
            # 当前页 <= 最多显示页数的一半,即显示前max_page_num条
            if self.current_page_num <= self.max_page_num_half:
                page_start = 1
                page_end = self.max_page_num + 1

            # 当前页 > 最多显示页数的一半
            else:
                # 显示最后的max_page_num条
                if (self.current_page_num + self.max_page_num_half) > self.all_pager:
                    page_start = self.all_pager - self.max_page_num_half + 1
                    page_end = self.all_pager + 1

                # 显示中间的max_page_num条
                else:
                    page_start = self.current_page_num - self.max_page_num_half
                    page_end = self.current_page_num + self.max_page_num_half + 1

        # 上一页 首页 页码 尾页 下一页
        page_html_list = []

        # 当前页为第一页时不可点击,当前页大于第一页时点击时当前页码-1
        if self.current_page_num <= 1:
            prev_page = '<li class="disabled paginate_button"><a href="#">上一页</a></li>'
        else:
            self.params['page'] = self.current_page_num - 1
            prev_page = '<li class="paginate_button"><a href="?%s">上一页</a></li>' % (self.params.urlencode(),)
        page_html_list.append(prev_page)

        # 首页
        first_page = '<li class="paginate_button"><a href="?page=%s">首页</a></li>' % (1,)
        page_html_list.append(first_page)

        # 页码
        for i in range(page_start, page_end):
            self.params['page'] = i
            if i == self.current_page_num:
                temp = '<li class="active paginate_button"><a href="%s">%s</a></li>' % (self.params.urlencode(), i)
            else:
                temp = '<li class="paginate_button"><a href="?%s">%s</a></li>' % (self.params.urlencode(), i)
            page_html_list.append(temp)

        # 尾页
        last_page = '<li class="paginate_button"><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)

        # 当前页为尾页时不可点击,当前页小于尾页时点击时当前页码+1
        if self.current_page_num >= self.all_pager:
            next_page = '<li class="disabled paginate_button"><a href="#">下一页</a></li>'
        else:
            self.params['page'] = self.current_page_num + 1
            next_page = '<li class="paginate_button"><a href="?%s">下一页</a></li>' % (self.params.urlencode(),)
        page_html_list.append(next_page)
        return ''.join(page_html_list)
自定义分页组件

视图函数中的使用

# 分页 注意分页应用了切片,但是一旦切片就不能再filter
        current_page_num = request.GET.get("page")
        pagination = Pagination(
            current_page_num,
            customer_list.count(),
            request,
            per_page_num=5)
        customer_list = customer_list[pagination.start:pagination.end]

模板中的使用

{{ pagination.page_html|safe }}
页码渲染
表单渲染时使用切片后的数据,即可实现分页

Cookie与Session

我们知道HTTP协议是无状态协议,也就是说每个请求都是独立的!无法记录前一次请求的状态。但HTTP协议中可以使用Cookie来完成会话跟踪!在Web开发中,使用session来完成会话跟踪,session底层依赖Cookie技术。 

cookie

其实Cookie是key-value结构,类似于一个python中的字典。随着服务器端的响应发送给客户端浏览器。然后客户端浏览器会把Cookie保存起来,当下一次再访问服务器时把Cookie再发送给服务器。 Cookie是由服务器创建,然后通过响应发送给客户端的一个键值对。客户端会保存Cookie,并会标注出Cookie的来源(哪个服务器的Cookie)。当客户端向服务器发出请求时会把所有这个服务器Cookie包含在请求中发送给服务器,这样服务器就可以识别客户端了!

  •  Cookie大小上限为4KB; 
  •  一个服务器最多在客户端浏览器上保存20个Cookie; 
  •  一个浏览器最多保存300个Cookie;  

cookie与HTTP头

Cookie是通过HTTP请求和响应头在客户端和服务器端传递的: 

  • Cookie:请求头,客户端发送给服务器端; 
  • 格式:Cookie: a=A; b=B; c=C。即多个Cookie用分号离开;  Set-Cookie:响应头,服务器端发送给客户端; 
  • 一个Cookie对象一个Set-Cookie: Set-Cookie: a=A Set-Cookie: b=B Set-Cookie: c=C  

cookie的覆盖

如果服务器端发送重复的Cookie那么会覆盖原有的Cookie,例如客户端的第一个请求服务器端发送的Cookie是:Set-Cookie: a=A;第二请求服务器端发送的是:Set-Cookie: a=AA,那么客户端只留下一个Cookie,即:a=AA。 

django中的cookie语法

设置cookie:

rep = HttpResponse(...) 或 rep = render(request, ...) 或 rep = redirect()
  
rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...) 

获取cookie:

request.COOKIES

删除cookie:

response.delete_cookie("cookie_key",path="/",domain=name)

session

Session是服务器端技术,利用这个技术,服务器在运行时可以 为每一个用户的浏览器创建一个其独享的session对象,由于 session为用户浏览器独享,所以用户在访问服务器的web资源时 ,可以把各自的数据放在各自的session中,当用户再去访问该服务器中的其它web资源时,其它web资源再从用户各自的session中 取出数据为用户服务。

django中的session语法

1、设置Sessions值
          request.session['session_name'] ="admin"
2、获取Sessions值
          session_name = request.session["session_name"]
3、删除Sessions值
          del request.session["session_name"]
4、flush() 
     删除当前的会话数据并删除会话的Cookie。
     这用于确保前面的会话数据不可以再次被用户的浏览器访问
5、get(key, default=None)
  
fav_color = request.session.get('fav_color', 'red')
  
6、pop(key)
  
fav_color = request.session.pop('fav_color')
  
7、keys()
  
8、items()
  
9、setdefault()
用户session的随机字符串
        request.session.session_key
   
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
   
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
   
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
   
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

补充语法
more

session配置

Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
   
a. 配置 settings.py
   
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
       
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
    SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

用户认证组件auth

auth模块

from django.contrib import auth

django.contrib.auth中提供了许多方法,这里主要介绍其中的三个:

authenticate()

提供了用户认证,即验证用户名以及密码是否正确,一般需要username  password两个关键字参数

如果认证信息有效,会返回一个  User  对象。authenticate()会在User 对象上设置一个属性标识那种认证后端认证了该用户,且该信息在后面的登录过程中是需要的。当我们试图登陆一个从数据库中直接取出来不经过authenticate()的User对象会报错的!!

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

login(HttpRequest,user)

该函数接受一个HttpRequest对象,以及一个认证了的User对象
此函数使用django的session框架给某个已认证的用户附加上session id等信息。
from django.contrib.auth import authenticate, login
   
def my_view(request):
  username = request.POST['username']
  password = request.POST['password']
  user = authenticate(username=username, password=password)
  if user is not None:
    login(request, user)
    # Redirect to a success page.
    ...
  else:
    # Return an 'invalid login' error message.
    ...

logout(request) 注销用户

from django.contrib.auth import logout
   
def logout_view(request):
  logout(request)
  # Redirect to a success page.

该函数接受一个HttpRequest对象,无返回值。当调用该函数时,当前请求的session信息会全部清除。该用户即使没有登录,使用该函数也不会报错。

User对象

User 对象属性:username, password(必填项)password用哈希算法保存到数据库 

user对象的is_authenticated()

如果是真正的user 对象,返回值恒为True.用于检查用户是否已经通过了验证.

通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了验证,这个方法很重要,在后台用request.

user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

要求:

1  用户登陆后才能访问某些页面,

2  如果用户没有登录就访问该页面的话直接跳到登录页面

3  用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址

方法1:

def my_view(request):
  if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

方法2:

django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()

复制代码
from django.contrib.auth.decorators import login_required
      
@login_required
def my_view(request):
    
'''
复制代码

若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings文件中通过LOGIN_URL进行修改)。并传递  当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

2.2创建用户

使用 create_user 辅助函数创建用户:

from django.contrib.auth.models import User
user = User.objects.create_user(username='',password='',email='')

2.3 check_password(password)

用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True

2.4  修改密码

使用 set_password() 来修改密码

user = User.objects.get(username='')
user.set_password(password='')
user.save 
def sign_up(request):
 
    state = None
    if request.method == 'POST':
 
        password = request.POST.get('password', '')
        repeat_password = request.POST.get('repeat_password', '')
        email=request.POST.get('email', '')
        username = request.POST.get('username', '')
        if User.objects.filter(username=username):
                state = 'user_exist'
        else:
                new_user = User.objects.create_user(username=username, password=password,email=email)
                new_user.save()
 
                return redirect('/book/')
    content = {
        'state': state,
        'user': None,
    }
    return render(request, 'sign_up.html', content)  

注册代码
register
@login_required
def set_password(request):
    user = request.user
    state = None
    if request.method == 'POST':
        old_password = request.POST.get('old_password', '')
        new_password = request.POST.get('new_password', '')
        repeat_password = request.POST.get('repeat_password', '')
        if user.check_password(old_password):
            if not new_password:
                state = 'empty'
            elif new_password != repeat_password:
                state = 'repeat_error'
            else:
                user.set_password(new_password)
                user.save()
                return redirect("/log_in/")
        else:
            state = 'password_error'
    content = {
        'user': user,
        'state': state,
    }
    return render(request, 'set_password.html', content)

修改密码的代码
password
原文地址:https://www.cnblogs.com/jiaqi-666/p/9892383.html