今日内容 choices参数 应用: 用户性别 用户学历 工作状态 客户来源 是否结婚 username gender 性别 jason 1 MTV与MVC模型 django框架 自称为是MTV框架 M:models T:templates V:views MVC M:models V:views C:controller 控制器(urls) 本质:MTV其实也是MVC Ajax 异步提交 局部刷新 请求方式 GET POST a标签href属性 GET请求 浏览器窗口输入url GET请求 form表单 GET/POST ajax GET/POST 首先ajax这门技术 是js中的 但是原生的js操作ajax比较繁琐,我们这里为了提高效率 直接使用jQuery封装版本的ajax AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。 (这一特点给用户的感受是在不知不觉中完成请求和响应过程) 小例子 页面上有三个input框 在前两个input框中输入数字 点击按钮 发送ajax请求 不刷新页面的情况下 第三个框中 自动算出两数之和 $('#b1').on('click',function () { {#alert(123)#} // 点击按钮 朝后端发送post请求 $.ajax({ url:'', // 控制发送给谁 不写就是朝当前地址提交 type:'post', // 发送方式是post请求 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, // 发送的数据 success:function (data) { // data形参用来接收异步提交的结果 {#alert(data)#} // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中 $('#i3').val(data) } }) }) contentType前后端传输数据编码格式 前后端传输数据编码格式 1.urlencoded 2.formdata 3.json form表单 默认使用的编码格式是urlencoded 数据格式:name=jason&pwd=123 django后端针对urlencoded编码格式的数据会自动解析并放到request.POST中供用户获取 可以修改为formdata 传文件 django后端针对只要是符合urlencoded编码格式的数据(name=jason&pwd=123)都会自动解析并放到request.POST中供用户获取 如果是文件 只要你指定的编码是formdata 就会自动解析并放到request.FILES中 总结:前后端传输数据的时候 一定要保证数据格式和你的编码格式是一致的 不能骗人家!!! ajax提交数据 ajax默认数据提交方式也是urlencoded ajax发送json格式数据 django后端针对json格式的数据 并不会自动解析放到request.POST或者request.FILES里面 它并不会解析json格式数据 而是将它原封不动的放在request.body中了 $('#b1').on('click',function () { alert(123) // 点击按钮 朝后端发送post请求 $.ajax({ url:'', // 控制发送给谁 不写就是朝当前地址提交 type:'post', // 发送方式是post请求 data:JSON.stringify({'username':'jason','password':123}), // 发送的数据 contentType:'application/json', // 告诉后端你这次的数据是json格式 success:function (data) { // data形参用来接收异步提交的结果 alert(data) // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中 $('#i3').val(data) } }) // {) ajax传输文件 // ajax传输文件 $('#b1').on('click',function () { // ajax传输文件 建议使用内置对象formdata var formData = new FormData(); // 既可以传普通的键值对 也可以传文件 // 添加普通键值 formData.append('username','jason'); formData.append('password','123'); // 传文件 // 如何获取文件标签所存储的文件对象? 固定语法 // 1.先用jQery查找到存储文件的input标签 // 2.将jQuery对象转成原生js对象 // 3.利用原生js对象的方法 .files[0]获取到标签内部存储的文件对象 // 4.一定要指定两个参数都为false formData.append('my_file',$('#d1')[0].files[0]); $.ajax({ url:'', // 控制发送给谁 不写就是朝当前地址提交 type:'post', // 发送方式是post请求 data:formData, // 发送的数据 // ajax发送文件需要指定两个额外的参数 processData:false, // 告诉前端不要处理数据 contentType:false, // 不适用任何编码 因为formdata对象自身自带编码 django后端也能够识别formdata对象 success:function (data) { // data形参用来接收异步提交的结果 {#alert(data)#} // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中 $('#i3').val(data) } }) }) 序列化组件 from django.core import serializers # django自带的一个小型的序列化工具 def reg(request): user_list = models.User.objects.all() res = serializers.serialize('json',user_list) return render(request,'index.html',locals()) [{ "model": "app01.user", "pk": 1, "fields": { "username": "jason", "age": 18, "gender": 1 } }, { "model": "app01.user", "pk": 2, "fields": { "username": "tank", "age": 24, "gender": 3 } }, { "model": "app01.user", "pk": 3, "fields": { "username": "egon", "age": 73, "gender": 2 } }, { "model": "app01.user", "pk": 7, "fields": { "username": "kevin", "age": 29, "gender": 4 } }] sweetalert搭建页面 https://github.com/lipis/bootstrap-sweetalert 下载 sweetalert,放到 static 下 ,只要 dist 就可以 https://lipis.github.io/bootstrap-sweetalert/ 删除确认 自定义分页器 1 bulk_create() 批量插入数据 # for i in range(1000): # models.Book.objects.create(title='第%s本书'%i) # 上面这种方式 效率极低 l = [] for i in range(10000): l.append(models.Book(title='第%s本书'%i)) models.Book.objects.bulk_create(l) # 批量插入数据 自定义分页器的使用 后端代码 book_list = models.Book.objects.all() current_page = request.GET.get("page",1) all_count = book_list.count() page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10,pager_count=5) page_queryset = book_list[page_obj.start:page_obj.end] 前端代码 {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} {{ page_obj.page_html|safe }} 多对多表关系 三种创建方式
内容回顾 choices字段 只要是能够罗列出来的有限个选项的都可以使用choices字段来做 1.学历,工作经历,性别,工作状态,客户来源,婚嫁 gender_choices = ((1,'male'),(2,'female'),(3,'others')) gender = models.IntegerField(choices=gender_choices) # 当gender存的是gender_choices中罗列的数字 那么就会有对应关系 # 但是如果存的数字不存在 那么也不会报错 正常存储 只不过没有了对应关系而已 2. user_obj.gender # 结果是数字 user_obj.get_gender_display() # 拿到数字所对应的注释 MTV与MVC模型 django自称为是MTV但是你要知道MTV其实本质也是MVC Ajax 异步提交 局部刷新 基本语法结构 $.ajax({ url:'', # 默认不写就是当前路径(不写,后缀,全称) type:'post', # 请求方式 data:{'name':'jason'} # 数据 数据默认的格式是urlencoded(name=jason&pwd=123) success:function(data){ # data就是后返回的异步提交的结果 通常都是一个字典 if (data.code == 1000){ # 状态码是1000的情况需要走的逻辑 }elif(data.code == 2000){ # 状态码是2000的情况需要走的逻辑 }else{ # 其他情况 需要的操作 } } }) 通常情况下 后端针对ajax交互 都是采取字典的形式 contentType 前后端传输数据的编码方式 1.urlencoded >>> name=jason&pwd=123&hobby=read 2.formdata >>> 传文件也支持传普通键值(name=jason&pwd=123&hobby=read) 3.application/json >>> json格式数据(form表单是无法发送json格式数据的) form,ajax表单默认的是urlencoded django后端针对不同的编码格式是如何处理的? 只要是符合urlencoded编码格式 都会被后端自动获取并解析放到request.POST中 如果是符合formdata那么文件会自动被解析放到request.FILES中 如果是json格式 后端默认不解析 以二进制的形式就放在request.body你可以自己手动处理即可 ajax发送json格式数据 """前后端传输数据 一定要确保数据与编码方式的一致性""" $.ajax({ url:'', # 默认不写就是当前路径(不写,后缀,全称) type:'post', # 请求方式 data:JSON.stringify({'name':'jason'}), # 数据 数据默认的格式是urlencoded(name=jason&pwd=123) contentType:'application/json', success:function(data){ # data就是后返回的异步提交的结果 通常都是一个字典 if (data.code == 1000){ # 状态码是1000的情况需要走的逻辑 }elif(data.code == 2000){ # 状态码是2000的情况需要走的逻辑 }else{ # 其他情况 需要的操作 } } }) ajax发送文件 1.利用内置对象FormData 既可以传文件也可以传普通的键值对 2.获取input标签存储的文件对象 先用jQuery找到该input标签,然后转成原生的js对象 然后固定语法.files[0] $('input')[0].files[0] 3.发送ajax请求 有两个关键性的参数需要你指定 processData:false contentType:false django后端就会普通的键值解析到request.POST中文件解析到request.FILES sweetalert 注意推导思路 删除弹框 作业:图书管理的系统的删除书籍功能 序列化组件 from django.core import serializers 自定义分页器 1.quertset支持切片取值 需要你掌握的就是推导思路 后端 book_list = models.Book.objects.all() page_obj = Paganation(current_page= request.GET.get('page',1),all_count=book_list.count()) page_query = book_list[page_obj.start:page_obj.end] # 将page_query,page_obj传递到前端即可 前端 确保你的html页面引入了bootstrap文件 # for循环page_query展示数据 # page_obj.page_html|safe生成分页器页码样式
sweetalert搭建页面 https://github.com/lipis/bootstrap-sweetalert
下载 sweetalert,放到 static 下 ,只要 dist 就可以
https://lipis.github.io/bootstrap-sweetalert/
删除确认
""" Django settings for day57 project. Generated by 'django-admin startproject' using Django 1.11.11. For more information on this file, see https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.11/ref/settings/ """ import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = 'dqv&tvq)xbl$(g3m+=z%r+2e*9&f8-+w_=s4$r3_xt+83s3+9d' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'day57.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')] , 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'day57.wsgi.application' # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day57', 'USER':'root', 'PASSWORD':'llx20190411', 'HOST':'127.0.0.1', 'PORT':3306, 'CHARSET':'utf8' } } # Password validation # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static') ] LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }
templates
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'dist/sweetalert.min.js' %}"></script> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> {# {% for book in page_querset %}#} {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} {{ page_obj.page_html|safe }} </div> </div> </div> {#<nav aria-label="Page navigation">#} {# <ul class="pagination">#} {# <li>#} {# <a href="#" aria-label="Previous">#} {# <span aria-hidden="true">«</span>#} {# </a>#} {##} {# </li>#} {# {{ html|safe }}#} {# <li>#} {# <a href="#" aria-label="Next">#} {# <span aria-hidden="true">»</span>#} {# </a>#} {# </li>#} {# </ul>#} {#</nav>#} </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> </head> <body> {#<input type="text" id="i1">+<input type="text" id="i2">=<input type="text" id="i3">#} {#<input type="file" id="d1">#} {##} {#<button id="b1">求和</button>#} {#reg 自己处理 json#} {#{% for user in user_1 %}#} {# <p>{{ user }}</p>#} {##} {#{% endfor %}#} {# 利用 serializers 模块处理#} {{ res }} {#<h1>#} {# contentType前后端传输数据编码格式#} {# 前后端传输数据编码格式#} {# 1.urlencoded#} {# 2.formdata#} {# 3.json#} {#</h1>#} {#<h2>urlencoded</h2>#} {#<form action="" method="post">#} {# username:<input type="text" name="name">#} {# password:<input type="text" name="pwd">#} {# <input type="submit">#} {#</form>#} {#<h3>form-data</h3>#} {#<form action="" method="post" enctype="multipart/form-data">#} {# username:<input type="text" name="name">#} {# password:<input type="password" name="pwd">#} {# info:<input type="file" name="myfile">#} {# <input type="submit">#} {#</form>#} <script> {# ajax基础用法 前端 #} {#$('#b1').on('click',function () {#} {#alert(123);#} {# // 点击按钮 朝后端发送post请求#} {# $.ajax({#} {# url: '',// 控制发送给谁 不写就是朝当前地址提交#} {# type:'post', // 发送方式是post请求#} {# data:{'i1':$('#i1').val(),'i2':$('#i2').val()},// 发送的数据#} {# success:function (data) {// data形参用来接收异步提交的结果#} {#alert(data); // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中#} {# $('#i3').val(data)#} {##} {# }#} {# })#} {#{)#} {# ajax json格式发数据 #} {# $('#b1').on('click',function () {#} {#alert(123);#} {# // 点击按钮 朝后端发送post请求#} {# $.ajax({#} {# url: '',// 控制发送给谁 不写就是朝当前地址提交#} {# type:'post', // 发送方式是post请求#} {# data:JSON.stringify({'username':'jason','password':123}),// 发送的数据#} {# contentType:'application/json',// 告诉后端你这次的数据是json格式#} {# success:function (data) {// data形参用来接收异步提交的结果#} {#alert(data); // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中#} {# $('#i3').val(data)#} {##} {# }#} {# })#} {# })#} {# ajax 传输文件 #} $('#b1').on('click',function () { // ajax 传输文件建议使用内置对象formdata var formData = new FormData(); // 既可以传普通的键值对,也可以传文件 // 添加普通键值对 formData.append('username','jason'); formData.append('password','123'); //传文件 // 如何获取文件标签所存储的文件对象? 固定语法 // 1.先用jQery查找到存储文件的input标签 // 2.将jQuery对象转成原生js对象 // 3.利用原生js对象的方法 .files[0]获取到标签内部存储的文件对象 // 4.一定要指定两个参数都为false processData contentType formData.append('my_file',$('#d1')[0].files[0]); // 点击按钮 朝后端发送post请求 $.ajax({ url: '',// 控制发送给谁 不写就是朝当前地址提交 type:'post', // 发送方式是post请求 data:formData,// 发送的数据 // ajax发送文件需要指定两个额外的参数 processData:false,// 告诉前端不要处理数据 contentType:false,// 不适用任何编码 因为formdata对象自身自带编码 django后端也能够识别formdata对象 success:function (data) {// data形参用来接收异步提交的结果 {#alert(data); // 将后端计算好的结果 通过DOM操作 渲染到第三个input矿中#} $('#i3').val(data) } }) }) </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}"> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'dist/sweetalert.min.js' %}"></script> <style> div.sweet-alert h2{ padding-top: 10px; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2 class="text-center">数据展示</h2> <table class="table-striped table table-hover table-bordered"> <thead> <tr> <th>序号</th> <th>主键</th> <th>用户名</th> <th>年龄</th> <th>性别</th> <th>操作</th> </tr> </thead> <tbody> {% for user in user_list %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user.pk }}</td> <td>{{ user.username }}</td> <td>{{ user.age }}</td> <td>{{ user.get_gender_display }}</td> <td> <button class="btn btn-primary btn-sm">编辑</button> <button class="btn btn-danger btn-sm del" user_id="{{ user.pk }}">删除</button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.del').click(function () { // 获取当前标签 var $btnEle = $(this); swal({ title:"你确实要删吗?", text:"你要删了,你就准备跑路吧!", type:"warning", showCancelButton:true, confirmButtonClass:"btn-danger", confirmButtonText:"是的老子就要删!" , cancelButtonText: "算了,算了!", closeOnConfirm:false, showLoaderOnConfirm:true }, function () { // 朝后端发送ajax请求 $.ajax({ url:'', type:'post', data:{'delete_id':$btnEle.attr('user_id')}, success:function (data) { // 后端发字典过来 前端不需要你手动转 会自动帮你转换成js自定义对象 {#alert(data.msg,typeof data);#} if (data.code == 100){ {#window.location.href = '';// 不写就是条到当前页面#} // 通过DOM操作 实时改变页面 // 将被点击的删除按钮所在的那一行直接从DOM树中删掉 $btnEle.parent().parent().remove(); swal("删掉了!","赶紧回去收拾行李,准备跑路!","success"); }else{ swal("发生未知错误","估计有bug","info") } } }); }); }) </script> </body> </html>
from django.db import models # Create your models here. class User(models.Model): username = models.CharField(max_length=32) age = models.IntegerField() choices = ( (1,'男'),(2,'女'),(3,'其他') ) gender = models.IntegerField(choices=choices) """ 1 存choice里面罗列的数字与中文对应关系 print(user_obj.get_gender_display()) 只要是choices字段 在获取数字对应的注释 固定语法 get_choices字段名_display() 2 存没有罗列迟来的数字 不会报错 还是展示数字 """ class Book(models.Model): title = models.CharField(max_length=32)
import pymysql
pymysql.install_as_MySQLdb()
from django.test import TestCase # Create your tests here. import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE",'day57.settings') import django django.setup() from app01 import models """ 只要是choices字段 在获取数字对应的注释 固定语法 get_choices字段名_display() """ user_obj = models.User.objects.filter(pk=1).first() print(user_obj.get_gender_display())
"""day57 URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.11/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), url(r'^reg/',views.reg), url(r'^userlist/',views.userlist), url(r'^book/',views.book), ]
from django.shortcuts import render,reverse,HttpResponse,redirect from app01 import models # Create your views here. def index(request): """""" """ajax基础用法 后端""" # print(request.is_ajax()) # # 用来判断当前请求方式是否是ajax请求 # if request.is_ajax(): # if request.method == 'POST': # print(request.POST) # i1 = request.POST.get('i1') # i2 = request.POST.get('i2') # # 后端获取的前端数据 都是字符串格式 # res = int(i1)+int(i2) # return HttpResponse(res) # 验证前后端传输数据的编码格式 if request.method == 'POST': print('request.POST',request.POST) print('request.FILES',request.FILES) # print(request.body) # # # 后端 需要手动去request.body中获取json格式数据 自己处理 # json_str = request.body # import json # s = json_str.decode('utf-8') # ral_d = json.loads(s) # print(ral_d,type(ral_d)) return HttpResponse('OK') return render(request,'index.html') from django.core import serializers # django自带的一个小型的序列化工具 import json def reg(request): user_1ist = models.User.objects.all() # 将所有的数据都组织成一个符合json的一个个的字典 # user_1 = [] # for user_obj in user_1ist: # user_1.append(json.dumps({'username':user_obj.username,'age':user_obj.age,'gender':user_obj.get_gender_display()})) # 前端 bejson.com 查看乱码 # {"username": "llx", "age": 18, "gender": "\u7537"} res = serializers.serialize('json',user_1ist) return render(request,'index.html',locals()) from django.http import JsonResponse import time def userlist(request): if request.is_ajax(): time.sleep(3) """ 一般情况下,针对ajax请求,后端通常都是返回一个字典 """ back_dic = {'code':100,'msg':''} # 直接获取用户想删除的数据的id值 delete_id = request.POST.get('delete_id') # 直接利用queryset方法批量删除 # models.User.objects.filter(pk=delete_id).delete() # 要给后端返回一个消息 back_dic['msg'] = '真的删了' return JsonResponse(back_dic) user_list = models.User.objects.all() return render(request,'userlist.html',locals()) from app01.utils.mypage import Pagination def book(request): # for i in range(1000): # models.Book.objects.create(title=f'第{i}本书') # l = [] # for i in range(10000): # l.append(models.Book(title=f'第{i}本书')) # models.Book.objects.bulk_create(l) # 批量插入数据 """分页:自己推到的分页器代码 """ """http://127.0.0.1:8000/book/?page=1000""" # current_page = request.GET.get("page",1) # 获取用户想访问的页码 如果没有 默认展示第一页 # current_page = int(current_page) # per_page_num = 10 # 规定每页展示10条数据 # start_page = (current_page-1) * per_page_num # end_page = current_page * per_page_num # book_list = models.Book.objects.all()[start_page:end_page] # all_count = models.Book.objects.all().count() # page_num,more = divmod(all_count,per_page_num) # all_count / per_page_num ,more余数 # if more: # page_num += 1 # 有余数,加1页 # # 在后端生成分页器代码 然后传递给前端 # html = '' # xxx = current_page # if current_page < 6: # xxx = 6 # for i in range(xxx-5,xxx+6): # if i == current_page: # html += '<li class="active><a href="?page=%s">%s</a></li>'%(i,i) # else: # html += f'<li><a href="?page={i}">{i}</a></li>' # 使用封装好的自定义分页器 book_list = models.Book.objects.all() current_page = request.GET.get("page",1) all_count = book_list.count() page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=7) page_queryset = book_list[page_obj.start:page_obj.end] return render(request, 'booklist.html', locals()) """ per_page_num = 10 current_page start_page end_page 1 0 10 2 10 20 3 20 30 4 30 40 per_page_num = 5 current_page start_page end_page 1 0 5 2 5 10 3 10 15 4 15 20 start_page = (current_page - 1) * per_page_num end_page = current_page* per_page_num 10000 10 1000 10001 10 1001 """