Django 批量迁移数据 分页类 cookie session

批量迁移数据

单纯使用for循环添加,这样数据量过大速度会很慢。

from app01 import models
l=[]
for i in range(10000):
  book_obj = models.Book(title='老人与海%s'%i)
  l.append(book_obj)
  models.Book.objects.bulk_create(l)
# 当需要批量添加数据的时候,bulk_create可以很快的添加的数据
# 相当于只执行一次sql语句

models.Book.objects.count() # 可以数数据

分页类的使用

views.py
def home(request):
    current_page = request.GET.get('page', 1)  # 当前页应该从前端获取
    try:
        current_page = int(current_page)
    except:
        current_page = 1
    per_page = 10  # 每页显示的条数是固定的
    
    '''
    per_page = 10
    current_page  start_page  end_page
        1             0         10
        2             10        20
        3             20        30
    '''
    
    page_start = (current_page - 1) * per_page
    page_end = current_page * per_page
    book_list = models.Book.objects.all()[page_start:page_end]  # 切片
    
# 计算出总页数
    all_count = models.Book.objects.all().count()
    all_page, remainder = divmod(all_count, 10)
  
    # 如果有余数页数加1
    if remainder:
        all_page += 1
# 将分页标签循环 再传到html页面
    html = ''
    for i in range(1, all_page):
        html += '<li><a href="?page=%s">%s</a></li>' % (i, i)

    return render(request, 'home.html', locals())
home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
    <script src="{% static 'JS/bootstrap.min.js' %}"></script>
    <script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
</head>
<body>
    <table class="table-striped table text-center">
        <thead>
            <tr>
                <th class="text-center">id</th>
                <th class="text-center">书名</th>
            </tr>
        </thead>
        <tbody>
            {% for book in book_list %}
                <tr>
                    <td>{{ book.id }}</td>
                    <td>{{ book.title }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>

<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">&laquo;</span>
      </a>
    </li>
      {{ html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">&raquo;</span>
      </a>
    </li>
  </ul>
</nav>

</body>
</html>

分页类的使用

这是个类需要在Django根目录创建一个文件夹添加py文件,将它复制到py文件中导入使用。

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

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

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

使用

views.py
from utils import Mypage


def home(request):
    current_page = request.GET.get('page')  # 获取当前页

    all_count = models.Book.objects.count()  # 记录的总数量

    obj = Mypage.Pagination(current_page, all_count)  # 传入参数

    page_html = obj.page_html()  # 拿到类里面的html样式将它传到前端页面中
    book_list = models.Book.objects.all()[obj.start:obj.end]  # 查询 切片

    return render(request, 'home.html', locals())
home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
    {% load static %}
    <link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
    <script src="{% static 'JS/bootstrap.min.js' %}"></script>
    <script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
</head>
<body>
    <table class="table-striped table text-center">
        <thead>
            <tr>
                <th class="text-center">id</th>
                <th class="text-center">书名</th>
            </tr>
        </thead>
        <tbody>
            {% for book in book_list %}
                <tr>
                    <td>{{ book.id }}</td>
                    <td>{{ book.title }}</td>
                </tr>
            {% endfor %}
        </tbody>
    </table>
  {{ page_html|safe }}
</body>
</html>

Cookie与Session

http协议的四大特性:

  • 基于请求响应
  • 基于TCP/UDP协议之上的应用层协议
  • 无状态:不能保存用户信息
  • 无/短链接:请求一次回应一次,之后断开连接

无状态的特性导致http协议无法保存用户信息,为了让它能保存用户信息,就诞生了cookie。cookie将用户需要保存的信息以键值对的形式储存在浏览器上,每次访问服务器时浏览器会自动携带cookie,这样服务器就能通过cookie内容读取到需要信息。

语法

设置cookie:

rep =HttpResponse || render || redirect 
rep.set_cookie(key,value,...)  # 在返回过程中设置cookie
rep.set_cookie(key,value,max_age=5)
# max_age 表示cookie失效时间 5表示5秒
rep.set_signed_cookie(key,value,salt='加密盐',...)

获取cookie:

request.COOKIES.get(key)

删除cookie:

rep =HttpResponse || render || redirect
rep.delete_cookie(key)

实际应用

创建用户表,用来获取数据

models.py
from django.db import models


# Create your models here.

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
urls.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^home/', views.home),
    url(r'^logout/', views.logout),
    url(r'^index/', views.index)
]
views.py
from django.shortcuts import render, redirect, HttpResponse
from app01 import models


# Create your views here.

'''
由于需要判断比较多
所以需要添加装饰器
装饰器添加获取到从哪个页面跳转过来的功能
在跳转到login页面的时候,将跳转之前路径当作参数传到login页面
'''
def auth(func):
    def wrapper(request, *args, **kwargs):
        # visited_url:获取到 是从哪个页面跳转到登录页面的
        visited_url = request.get_full_path()
        status = request.COOKIES.get('is_online')
        if status:  # 判断浏览器是否携带cookie
            return func(request, *args, **kwargs)
        else:
            # 如果跳转到登录页面将获取到的visited_url作为参数传到login页面
            return redirect('/login/?visited=%s' % visited_url)

    return wrapper


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
        print(user_obj.username)
        if not user_obj:  # 如果没有查到输入的用户名密码
            return redirect('/login/')
        else:
            '''
            没有登录需要跳转到login页面
            在login页面 获取到装饰器传来的visited参数
            '''
            visited_url = request.GET.get('visited')
            if visited_url:  # 如果有值就表示是从其他页面跳转过来的
                rep = redirect(visited_url)  # 登录成功后就返回到之前的路径页面

            else:  # 没有值就回到home页面
                rep = redirect('/home/')
            rep.set_cookie('is_online', True)
            return rep
    return render(request, 'login.html')


@auth
def home(request):
    # status = request.COOKIES.get('is_online')
    # print(status)
    # if not status:  # 判断浏览器是否携带cookie
    #     return redirect('/login/')

    return render(request, 'home.html')


@auth
def index(request):
    return render(request, 'index.html')


def logout(request):
    # 点击logout 删除cookie 并返回到登录界面
    rep = redirect('/login/')
    rep.delete_cookie('is_online')
    return rep

模版html文件

login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'CSS/LOGIN.css' %}">
</head>
<body>
    <div id="big1">
        <h1 style="color: aliceblue">Login</h1>
        <form method="post" action="">
        <p><input type="text" required="required" placeholder="用户名" name="username"></p>
        <p><input type="password" required="required" placeholder="密码" name="password"></p>
            <button class="but" type="submit">登录</button>
 </form>
 </div>
</body>
</html>
home.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>home</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'CSS/bootstrap.min.css' %}">
</head>
<body>
    <h1>welcome home page</h1>
    <a href="/logout/" class="btn btn-danger">注销</a>
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
    {% load static %}
    <link rel="stylesheet" href="{% static 'CSS/bootstrap.min.css' %}">
</head>
<body>
    <h1>Here is index page</h1>
    <a href="/logout/" class="btn btn-danger ">注销</a>
</body>
</html>

session

cookie可以记录用户状态信息,但cookie的数据保存在浏览器端安全性较差。所以我们通常是通过cookie识别不同的用户,然后在session里保存私密的信息,django.session 表中保存的是浏览器信息,而不是每一个用户的信息。因此, 同一浏览器多个用户请求只保存一条记录(后面覆盖前面),多个浏览器请求才保存多条记录。

session默认过期时间为14天

request.session.set_expiry()
# 整数表示多少秒
# 设置具体时间

session设置语法:

request.session['key'] = value

设置session经历了哪些事?

  1. 生成了一个随机字符串。

  2. 操作了数据库

    临时把数据存到内存当中。

    响应走的的时候操作数据库,将设置的键值对保存到django_session表里面。

  3. 将随机字符串响应给浏览器。

session获取语法:

request.session.get('key')

获取session经历了哪些事?

  1. 自动从浏览器中获取cookie信息,即随机字符串。
  2. 根据随机字符串在django_session表中过滤出记录(没有返回None)。
  3. 如果有值的情况下那么django会把session数据封装到request.session中。

删除session语法

request.session.delete()  # 只删除服务端的 客户端的不删
request.session.flush()  # 浏览器和服务端都清空
# 删除 session_data 里的其中一组键值对:
del request.session["key"]

session实际应用

views.py
def s_auth(func):
    def wrapper(request, *args, **kwargs):
        visited_url = request.get_full_path()
        status = request.session.get('is_login')
        if status:
            return func(request, *args, **kwargs)
        else:
            return redirect('/s_login/?visited=%s' % visited_url)

    return wrapper


def s_login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        user_obj = models.UserInfo.objects.filter(username=username, password=password).first()
        if not user_obj:
            return redirect('/s_login/')
        else:
            visited_url = request.GET.get('visited')
            if visited_url:
                request.session['is_login'] = True
                request.session['user'] = username
                return redirect(visited_url)
            else:
                return redirect('/s_home/')
    return render(request, 'login.html')


@s_auth
def s_home(request):
    return render(request, 'home.html')


@s_auth
def s_index(request):
    return render(request, 'index.html')


def s_logout(request):
    del request.session['is_login']
    # request.session.flush()
    return redirect('/s_login/')

cookie和session语法用法需要注意区分开来。

posted @ 2021-08-23 23:37  popopop  阅读(42)  评论(0)    收藏  举报