Django 框架---------### 1、简介Django 是用python语言写的开源web开发框架,并遵循MVC设计。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以"插件"形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。### 2、特点### 1) 重量级框架对比Flask框架,Django原生提供了众多的功能组件,让开发更简便快速。> * 提供项目工程管理的自动化脚本工具> > * 数据库ORM支持(对象关系映射,英语:Object Relational Mapping)> > * 模板> > * 表单> > * Admin管理站点> > * 文件管理> > * 认证权限> > * session机制> > * 缓存### 2)MVT模式有一种程序设计模式叫MVC ,其核心思想是分工、解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容 。> MVC的全拼为Model-View-Controller ,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式,是为了将传统的输入(input)、处理(processing)、输出(output)任务运用到图形化用户交互模型中而设计的。随着标准输入输出设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。现在虽然不再使用原来的分工方式,但是这种分工的思想被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。后来,MVC的思想被应用在了Web开发方面,被称为Web MVC框架。Django的MVT
### 3、搭建虚拟环境Django框架(入门超细笔记 创建项目步骤 )_django创建项目-CSDN博客#### 3.1、在cmd中输入命令 > pip install virtualenv#### 3.2、创建虚拟环境##### 3.2.1、新建文件夹DjangoSpace
##### 3.2.2、执行命令virtualenv venv(虚拟环境目录名称可以任意)
##### 3.2.3 、在虚拟环境中安装Django框架进入到DjangoSpaceenvScripts目录下执行:pip install Django
安装成功后
### 4、创建Django项目 ### cmd中创建Django### 4.1、首先将路径切换到要创建Django项目的路径下
### 4.2、执行创建工程的命令 > **django-admin startproject**?``(项目名称)> 例如:创建一个学生管理系统> > django-admin startprojectstudentsystem
### 4.3、工程目录说明 查看创建的工程目录,结构如下:
> 与项目同名的目录,此处为studentsystem。> > settings.py 是项目的整体配置文件。> > urls.py是项目的URL配置文件。> > wsgi.py是项目与WSGI兼容的Web服务器入口。> > manage.py是项目管理文件,通过它管理项目### 4.4、 运行开发服务器在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。> 先设置用户:> > python manage.py migrate > >
> > 运行服务器命令:> > python manage.py runserver ip:端口 > 或:python manage.py runserver > >
> 注意:如果电脑有酷狗音乐一定要关掉,它有可能会占8000这个端口
django默认工作在调式Debug模式下,如果增加、修改、删除文件,服务器会自动重启****按ctrl+c停止服务器 ### 5、创建子应用 在Web应用中,通常有一些业务功能模块是在不同的项目中都可以复用的,故在开发中通常将工程项目拆分为不同的子功能模块,各功能模块间可以保持相对的独立,在其他工程项目中需要用到某个特定功能模块时,可以将该模块代码整体复制过去,达到复用。Django的视图编写是放在子应用中的。 ### (1)、创建APP 在Django中,创建子应用模块的仍然可以通过命令来操作,即> python manage.py startapp 子应用名称manage.py为上述创建工程时自动生成的管理文件。例如,在刚才创建的studentsystem工程中,想要创建一个用户student子应用模块,可执行:> python manage.py startapp student > >
### (2)、子应用目录说明****查看此时的工程目录,结构如下:
> admin.py 文件跟网站的后台管理站点配置相关。> > apps.py 文件用于配置当前子应用的相关信息。> > migrations 目录用于存放数据库迁移历史文件。> > models.py 文件用户保存数据库模型类。> > tests.py 文件用于开发测试用例,编写单元测试。> > views.py 文件用于编写Web应用视图函数。
创建出来的子应用目录文件虽然被放到了工程项目目录中,但是django工程并不能立即直接使用该子应用,需要注册安装后才能使用。在工程配置文件settings.py中,INSTALLED_APPS 项保存了工程中已经注册安装的子应用,初始工程中的INSTALLED_APPS如下:
注册安装一个子应用的方法,即是将子应用的配置信息文件apps.py中的Config类添加到INSTALLED_APPS列表中。例如,将刚创建的book子应用添加到工程中,可在INSTALLED_APPS列表中添加'book.apps.BookConfig' 。
pycharm创建我们的Django项目 ------------------------
用pycharm打开
创建好后
创建项目之前首先要安装Django和pymysql> pip install Django> > pip install pymysql模型--> * 当前项目的开发, 都是数据驱动的。> * 以下为书籍信息管理的数据关系:书籍和人物是 :一对多关系> > >
> > * 要先分析出项目中所需要的数据, 然后设计数据库表.> 书籍信息表 字段名字段类型字段说明idAutoField主键nameCharField书名idname1西游记2三国演义人物信息表 字段名字段类型字段说明idAutoField主键nameCharField人名genderBooleanField性别bookForeignKey外键idnamegenderbook1孙悟空False12白骨精True13曹操False24貂蝉True2使用Django进行数据库开发的提示 > * MVT设计模式中的Model, 专门负责和数据库交互.对应(models.py)> * 由于Model中内嵌了ORM框架, 所以不需要直接面向数据库编程.> * 而是定义模型类, 通过模型类和对象完成数据库表的增删改查.> * ORM框架就是把数据库表的行与相应的对象建立关联, 互相转换.使得数据库的操作面向对象.
### 使用Django进行数据库开发的步骤> 1. 定义模型类> > 2. 模型迁移> 3. 操作数据库### 1. 定义模型类* 根据书籍表结构设计模型类: > * 模型类:BookInfo > * 书籍名称字段:name * 根据人物表结构设计模型类: > * 模型类:PeopleInfo > * 人物姓名字段:name > * 人物性别字段:gender > * 外键约束:book > * 外键要指定所属的模型类book = models.ForeignKey(BookInfo) * 说明 : > * 书籍-人物的关系为一对多. 一本书中可以有多个英雄. > * 不需要定义主键字段, 在生成表时会自动添加, 并且值为自增长. * 根据数据库表的设计 > * 在models.py中定义模型类,继承自models.Model > > from django.db import models > > # Create your models here. > > ''' > 1.定义模型类 > 2.模型迁移 > 2.1 先生成迁移文件(不会在数据库中生成表,只会创建一个数据表和模型的对应关系) > python manage.py makemigrations > 2.2 再迁移(会在数据库中生成表) > 3.操作数据库 > > 在哪里定义模型 > 模型继承自谁就可以 > ORM对应的关系 > 表-->类 > 字段-->属性 > ''' > > # 准备书籍列表信息的模型类 > class BookInfo(models.Model): > # 创建字段,字段类型... > # 1、主键 当前会自动生成 > # 2、属性 > name = models.CharField(max_length=10) > > # 准备人物列表信息的模型类 > class PeopleInfo(models.Model): > # 姓名 > name = models.CharField(max_length=10) > # 性别 > gender = models.BooleanField() > # 外键约束:人物属于哪本书 > book = models.ForeignKey(BookInfo,on_delete=models.CASCADE) ### 2. 模型迁移 (建表)> * 迁移由两步完成> > > 生成迁移文件:根据模型类生成创建表的语句> > python manage.py makemigrations > > 执行迁移:根据第一步生成的语句在数据库中创建表> > * 迁移前> > >
> > * 迁移后> > >
> >
> 提示:默认采用 sqlite3数据库来存储数据 注意事项
解决办法
注意事项
看不到数据库表解决办法
运行 
--------------------------------------------------------------------------------中文显示(改后刷新页面) 
--------------------------------------------------------------------------------站点管理----* 站点 : 分为内容发布和公共访问两部分* 内容发布 的部分由网站的管理员负责查看、添加、修改、删除数据* Django能够根据定义的模型类自动地生成管理模块* 使用Django的管理模块, 需要按照如下步骤操作 : > * 1.管理界面本地化 > * 2.创建管理员 > * 3.注册模型类 > * 4.发布内容到数据库 ### 1.管理界面本地化> * 本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化.> * 中国大陆地区使用简体中文, 时区使用亚洲/上海时区, 注意这里不使用北京时区.> * 本地化前
> > * 本地化后
> ### 2.创建管理员* 创建管理员的命令 > python manage.py createsuperuser * 按提示输入用户名、邮箱、密码
注意:要用超级管理员 admin Zw23456...!* 重置密码 > python manager.py changepassword 用户名
* 登陆站点**http://127.0.0.1:8000/admin** * 需要服务器是启动状态
* 登陆站点成功 * 站点界面中没有书籍和人物管理入口,因为没有注册模型类
### 3.注册模型类* 在应用的admin.py文件中注册模型类 * 需要导入模型模块from book.models import BookInfo,PeopleInfo
* 注册模型后
> 注册模型成功后, 就可以在站点管理界面方便快速的管理数据. ### 4.发布内容到数据库### 
* 发布内容后,优化模型类展示
视图和URL------> * 站点管理页面做好了, 接下来就要做公共访问的页面了.> * 对于Django的设计框架MVT.> * 用户在URL中请求的是视图.> * 视图接收请求后进行处理.> * 并将处理的结果返回给请求者.> * 使用视图时需要进行两步操作> * 1.定义视图> * 2.配置URLconf### 1. 定义视图> * 视图就是一个Python函数,被定义在应用的views.py中.> * 视图的第一个参数是HttpRequest类型的对象reqeust,包含了所有请求信息.> * 视图必须返回HttpResponse对象,包含返回给请求者的响应信息.> * 需要导入HttpResponse模块 :from django.http import HttpResponse> > * 定义视图函数 : 响应字符串OK!给客户端
> > 思考 : 如何才能让请求找到视图 ### 2. 配置URLconf> * 查找视图的过程 :> > * 1.请求者在浏览器地址栏中输入URL, 请求到网站.> * 2.网站获取URL信息.> * 3.然后与编写好的URLconf逐条匹配.> * 4.如果匹配成功则调用对应的视图.> * 5.如果所有的URLconf都没有匹配成功.则返回404错误.
> > * URLconf入口
> > * 需要两步完成URLconf配置> > * 1.在项目中定义URLconf> * 2.在应用中定义URLconf> * 在项目中定义URLconf
> > > """bookmanager URL Configuration> > The urlpatterns list routes URLs to views. For more information please see:> https://docs.djangoproject.com/en/3.2/topics/http/urls/\> Examples:> Function views> 1. Add an import: from my_app import views> 2. Add a URL to urlpatterns: path('', views.home, name='home')> Class-based views> 1. Add an import: from other_app.views import Home> 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')> Including another URLconf> 1. Import the include() function: from django.urls import include, path> 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))> """> from django.contrib import admin> from django.urls import path,include> > > '''> 1、urlpatterns 是固定写法,值是列表> 2、浏览器中输入的路径会和urlpatterns 中的每一项顺序进行匹配> 如果匹配成功,则直接引导到相应的模块> 如果匹配不成功,则直接返回404> 3、urlpatterns中的元素是 url> url 的第一个参数是:正则> r 转义> ^ 严格的开始> $ 严格的结尾> 4、浏览器中输入的路由 中 哪些部分参与正则匹配> http://ip:port/path/?key=value> http://ip:port/ 和 get post 参数不参与正则匹配> 5、如果和当前的某一项匹配成功,则引导到子应用中继续匹配> 如果匹配成功,则停止匹配返回相应的视图> 如果匹配不成功,则继承和后边的工程中的url的每一项继续匹配,直到匹配每一项> 6、> '''> > urlpatterns = \> # http://127.0.0.1:8000/admin/\> # http://127.0.0.1:8000\> # admin/?a=100\> # admin/\> path('admin/', admin.site.urls),\> \> # 添加一项\> path('',include('book.urls'))\> > > > > > > > > > * 在应用中定义URLconf> > * 提示:一条URLconf包括URL规则、视图两部分> > * URL规则使用正则表达式定义.> * 视图就是在views.py中定义的视图函数
> > from django.urls import path> from book.views import index> > urlpatterns = \> # index/\> # url的第一个参数是:正则\> # url的第二个参数是:视图函数名\> path('index/',index),\> > > * url匹配过程
> ### 3. 测试:请求访问* http://127.0.0.1:8000/index
### 4. 总结视图处理过程如下图:
> 使用视图时需要进行两步操作,两步操作不分先后> > 1. 配置URLconf> 2. 在应用/views.py中定义视图
模板--> 思考 : 网站如何向客户端返回一个漂亮的页面呢?> * 提示 :> > * 漂亮的页面需要html、css、js.> * 可以把这一堆字段串全都写到视图中, 作为HttpResponse()的参数,响应给客户端.> * 问题 :> > * 视图部分代码臃肿, 耦合度高.> * 这样定义的字符串是不会出任何效果和错误的.> * 效果无法及时查看.有错也不容易及时发现.> * 设想 :> > * 是否可以有一个专门定义前端页面的地方, 效果可以及时展示,错误可以及时发现,并且可以降低模块间耦合度!> * 解决问题 :模板 > > * MVT设计模式中的T,Template> * 在 Django中, 将前端的内容定义在模板中, 然后再把模板交给视图调用, 各种漂亮、炫酷的效果就出现了. > ### 模板使用步骤> * 1.创建模板> * 2.设置模板查找路径> * 3.模板接收视图传入的数据> * 4.模板处理数据#### 1.创建模板> * 在应用同级目录下创建模板文件夹templates. 文件夹名称固定写法.> * 在templates文件夹下, 创建应用同名文件夹. 例,Book> * 在应用同名文件夹下创建网页模板文件. 例 :index.html> > >
#### 2.设置模板查找路径
#### 3.模板接收视图传入的数据* > 视图模板加载 ####
#### 4.模板处理数据
#### 5. 查看模板处理数据成果
总结
展示书籍列表------### 需求
#### 实现步骤> * 1.创建视图> * 2.创建模板> * 3.配置URLconf#### 1.创建视图> * 查询数据库数据> * 构造上下文> * 传递上下文到模板> from django.shortcuts import render from django.http import HttpRequest,HttpResponse from book.models import BookInfo # Create your views here. def index(request): # 实现业务逻辑 # 1、先把所有书籍查询出来 # ORM 实现 books = BookInfo.objects.all() # books = BookInfo(), # 2、组织数据 context = { 'books':books } # 3、将组织好的数据传递给模板 return render(request,'index.html',context)#### 2.创建模板* 读取上下文数据* 构造网页html文档 : 书籍信息以列表样式展示
Title
[书籍列表](### 1、简介Django 是用python语言写的开源web开发框架,并遵循MVC设计。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以"插件"形式服务于整个框架,Django有许多功能强大的第三方插件,你甚至可以很方便的开发出自己的工具包。这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。### 2、特点### 1) 重量级框架对比Flask框架,Django原生提供了众多的功能组件,让开发更简便快速。> * 提供项目工程管理的自动化脚本工具> > * 数据库ORM支持(对象关系映射,英语:Object Relational Mapping)> > * 模板> > * 表单> > * Admin管理站点> > * 文件管理> > * 认证权限> > * session机制> > * 缓存### 2)MVT模式有一种程序设计模式叫MVC,其核心思想是分工、解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。> MVC的全拼为Model-View-Controller,最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一种软件设计模式,是为了将传统的输入(input)、处理(processing)、输出(output)任务运用到图形化用户交互模型中而设计的。随着标准输入输出设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。现在虽然不再使用原来的分工方式,但是这种分工的思想被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。后来,MVC的思想被应用在了Web开发方面,被称为Web MVC框架。Django的MVT ### 3、搭建虚拟环境Django框架(入门超细笔记 创建项目步骤 )_django创建项目-CSDN博客#### 3.1、在cmd中输入命令> pip install virtualenv#### 3.2、创建虚拟环境##### 3.2.1、新建文件夹DjangoSpace ##### 3.2.2、执行命令virtualenv venv(虚拟环境目录名称可以任意) ##### 3.2.3 、在虚拟环境中安装Django框架进入到DjangoSpaceenvScripts目录下执行:pip install Django 安装成功后 ### 4、创建Django项目### cmd中创建Django### 4.1、首先将路径切换到要创建Django项目的路径下 ### 4.2、执行创建工程的命令> django-admin startproject?(项目名称)> 例如:创建一个学生管理系统> > django-admin startprojectstudentsystem ### 4.3、工程目录说明 查看创建的工程目录,结构如下: > 与项目同名的目录,此处为studentsystem。> > settings.py 是项目的整体配置文件。> > urls.py是项目的URL配置文件。> > wsgi.py是项目与WSGI兼容的Web服务器入口。> > manage.py是项目管理文件,通过它管理项目### 4.4、 运行开发服务器在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。> 先设置用户:> > python manage.py migrate> > > > 运行服务器命令:> > python manage.py runserver ip:端口 > 或:python manage.py runserver> > > 注意:如果电脑有酷狗音乐一定要关掉,它有可能会占8000这个端口 django默认工作在调式Debug模式下,如果增加、修改、删除文件,服务器会自动重启****按ctrl+c停止服务器### 5、创建子应用在Web应用中,通常有一些业务功能模块是在不同的项目中都可以复用的,故在开发中通常将工程项目拆分为不同的子功能模块,各功能模块间可以保持相对的独立,在其他工程项目中需要用到某个特定功能模块时,可以将该模块代码整体复制过去,达到复用。Django的视图编写是放在子应用中的。### (1)、创建APP在Django中,创建子应用模块的仍然可以通过命令来操作,即> python manage.py startapp 子应用名称manage.py为上述创建工程时自动生成的管理文件。例如,在刚才创建的studentsystem工程中,想要创建一个用户student子应用模块,可执行:> python manage.py startapp student> > ### (2)、子应用目录说明****查看此时的工程目录,结构如下: > admin.py 文件跟网站的后台管理站点配置相关。> > apps.py 文件用于配置当前子应用的相关信息。> > migrations 目录用于存放数据库迁移历史文件。> > models.py 文件用户保存数据库模型类。> > tests.py 文件用于开发测试用例,编写单元测试。> > views.py 文件用于编写Web应用视图函数。 创建出来的子应用目录文件虽然被放到了工程项目目录中,但是django工程并不能立即直接使用该子应用,需要注册安装后才能使用。在工程配置文件settings.py中,INSTALLED_APPS项保存了工程中已经注册安装的子应用,初始工程中的INSTALLED_APPS如下: 注册安装一个子应用的方法,即是将子应用的配置信息文件apps.py中的Config类添加到INSTALLED_APPS列表中。例如,将刚创建的book子应用添加到工程中,可在INSTALLED_APPS列表中添加’book.apps.BookConfig’。 pycharm创建我们的Django项目------------------------ 用pycharm打开 创建好后 创建项目之前首先要安装Django和pymysql> pip install Django> > pip install pymysql模型–> * 当前项目的开发, 都是数据驱动的。> * 以下为书籍信息管理的数据关系:书籍和人物是 :一对多关系> > > > > * 要先分析出项目中所需要的数据, 然后设计数据库表.> 书籍信息表字段名字段类型字段说明idAutoField主键nameCharField书名idname1西游记2三国演义人物信息表字段名字段类型字段说明idAutoField主键nameCharField人名genderBooleanField性别bookForeignKey外键idnamegenderbook1孙悟空False12白骨精True13曹操False24貂蝉True2使用Django进行数据库开发的提示> * MVT设计模式中的Model, 专门负责和数据库交互.对应(models.py)> * 由于Model中内嵌了ORM框架, 所以不需要直接面向数据库编程.> * 而是定义模型类, 通过模型类和对象完成数据库表的增删改查.> * ORM框架就是把数据库表的行与相应的对象建立关联, 互相转换.使得数据库的操作面向对象. ### 使用Django进行数据库开发的步骤> 1. 定义模型类> > 2. 模型迁移> 3. 操作数据库### 1. 定义模型类* 根据书籍表结构设计模型类: > * 模型类:BookInfo > * 书籍名称字段:name * 根据人物表结构设计模型类: > * 模型类:PeopleInfo > * 人物姓名字段:name > * 人物性别字段:gender > * 外键约束:book > * 外键要指定所属的模型类book = models.ForeignKey(BookInfo) * 说明 : > * 书籍-人物的关系为一对多. 一本书中可以有多个英雄. > * 不需要定义主键字段, 在生成表时会自动添加, 并且值为自增长. * 根据数据库表的设计 > * 在models.py中定义模型类,继承自models.Model > > from django.db import models > > # Create your models here. > > ‘’’ > 1.定义模型类 > 2.模型迁移 > 2.1 先生成迁移文件(不会在数据库中生成表,只会创建一个数据表和模型的对应关系) > python manage.py makemigrations > 2.2 再迁移(会在数据库中生成表) > 3.操作数据库 > > 在哪里定义模型 > 模型继承自谁就可以 > ORM对应的关系 > 表–>类 > 字段–>属性 > ‘’’ > > # 准备书籍列表信息的模型类 > class BookInfo(models.Model): > # 创建字段,字段类型… > # 1、主键 当前会自动生成 > # 2、属性 > name = models.CharField(max_length=10) > > # 准备人物列表信息的模型类 > class PeopleInfo(models.Model): > # 姓名 > name = models.CharField(max_length=10) > # 性别 > gender = models.BooleanField() > # 外键约束:人物属于哪本书 > book = models.ForeignKey(BookInfo,on_delete=models.CASCADE) ### 2. 模型迁移 (建表)> * 迁移由两步完成> > > 生成迁移文件:根据模型类生成创建表的语句> > python manage.py makemigrations> > 执行迁移:根据第一步生成的语句在数据库中创建表> > * 迁移前> > > > > * 迁移后> > > > > > 提示:默认采用sqlite3数据库来存储数据注意事项 解决办法 注意事项 看不到数据库表解决办法 运行 --------------------------------------------------------------------------------中文显示(改后刷新页面) --------------------------------------------------------------------------------站点管理----* 站点: 分为内容发布和公共访问两部分* 内容发布的部分由网站的管理员负责查看、添加、修改、删除数据* Django能够根据定义的模型类自动地生成管理模块* 使用Django的管理模块, 需要按照如下步骤操作 : > * 1.管理界面本地化 > * 2.创建管理员 > * 3.注册模型类 > * 4.发布内容到数据库 ### 1.管理界面本地化> * 本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化.> * 中国大陆地区使用简体中文, 时区使用亚洲/上海时区, 注意这里不使用北京时区.> * 本地化前 > > * 本地化后 > ### 2.创建管理员* 创建管理员的命令 > python manage.py createsuperuser* 按提示输入用户名、邮箱、密码 注意:要用超级管理员 admin Zw23456…!* 重置密码 > python manager.py changepassword 用户名 * 登陆站点**http://127.0.0.1:8000/admin** * 需要服务器是启动状态 * 登陆站点成功 * 站点界面中没有书籍和人物管理入口,因为没有注册模型类 ### 3.注册模型类* 在应用的admin.py文件中注册模型类 * 需要导入模型模块from book.models import BookInfo,PeopleInfo * 注册模型后 > 注册模型成功后, 就可以在站点管理界面方便快速的管理数据.### 4.发布内容到数据库### * 发布内容后,优化模型类展示 视图和URL------> * 站点管理页面做好了, 接下来就要做公共访问的页面了.> * 对于Django的设计框架MVT.> * 用户在URL中请求的是视图.> * 视图接收请求后进行处理.> * 并将处理的结果返回给请求者.> * 使用视图时需要进行两步操作> * 1.定义视图> * 2.配置URLconf### 1. 定义视图> * 视图就是一个Python函数,被定义在应用的views.py中.> * 视图的第一个参数是HttpRequest类型的对象reqeust,包含了所有请求信息.> * 视图必须返回HttpResponse对象,包含返回给请求者的响应信息.> * 需要导入HttpResponse模块 :from django.http import HttpResponse> > * 定义视图函数 : 响应字符串OK!给客户端 > > 思考 : 如何才能让请求找到视图### 2. 配置URLconf> * 查找视图的过程 :> > * 1.请求者在浏览器地址栏中输入URL, 请求到网站.> * 2.网站获取URL信息.> * 3.然后与编写好的URLconf逐条匹配.> * 4.如果匹配成功则调用对应的视图.> * 5.如果所有的URLconf都没有匹配成功.则返回404错误. > > * URLconf入口 > > * 需要两步完成URLconf配置> > * 1.在项目中定义URLconf> * 2.在应用中定义URLconf> * 在项目中定义URLconf > > > “”“bookmanager URL Configuration> > The urlpatterns list routes URLs to views. For more information please see:> https://docs.djangoproject.com/en/3.2/topics/http/urls/> Examples:> Function views> 1. Add an import: from my_app import views> 2. Add a URL to urlpatterns: path(‘’, views.home, name=‘home’)> Class-based views> 1. Add an import: from other_app.views import Home> 2. Add a URL to urlpatterns: path(‘’, Home.as_view(), name=‘home’)> Including another URLconf> 1. Import the include() function: from django.urls import include, path> 2. Add a URL to urlpatterns: path(‘blog/’, include(‘blog.urls’))> “””> from django.contrib import admin> from django.urls import path,include> > > ‘’‘> 1、urlpatterns 是固定写法,值是列表> 2、浏览器中输入的路径会和urlpatterns 中的每一项顺序进行匹配> 如果匹配成功,则直接引导到相应的模块> 如果匹配不成功,则直接返回404> 3、urlpatterns中的元素是 url> url 的第一个参数是:正则> r 转义> ^ 严格的开始> $ 严格的结尾> 4、浏览器中输入的路由 中 哪些部分参与正则匹配> http://ip:port/path/?key=value> http://ip:port/ 和 get post 参数不参与正则匹配> 5、如果和当前的某一项匹配成功,则引导到子应用中继续匹配> 如果匹配成功,则停止匹配返回相应的视图> 如果匹配不成功,则继承和后边的工程中的url的每一项继续匹配,直到匹配每一项> 6、> ‘’’> > urlpatterns = [> # http://127.0.0.1:8000/admin/> # http://127.0.0.1:8000> # admin/?a=100> # admin/> path(‘admin/’, admin.site.urls),> > # 添加一项> path(‘’,include(‘book.urls’))> ]> > > > > > > > > * 在应用中定义URLconf> > * 提示:一条URLconf包括URL规则、视图两部分> > * URL规则使用正则表达式定义.> * 视图就是在views.py中定义的视图函数 > > from django.urls import path> from book.views import index> > urlpatterns = [> # index/> # url的第一个参数是:正则> # url的第二个参数是:视图函数名> path(‘index/’,index),> ]> > * url匹配过程 > ### 3. 测试:请求访问* http://127.0.0.1:8000/index ### 4. 总结视图处理过程如下图: > 使用视图时需要进行两步操作,两步操作不分先后> > 1. 配置URLconf> 2. 在应用/views.py中定义视图 模板–> 思考 : 网站如何向客户端返回一个漂亮的页面呢?> * 提示 :> > * 漂亮的页面需要html、css、js.> * 可以把这一堆字段串全都写到视图中, 作为HttpResponse()的参数,响应给客户端.> * 问题 :> > * 视图部分代码臃肿, 耦合度高.> * 这样定义的字符串是不会出任何效果和错误的.> * 效果无法及时查看.有错也不容易及时发现.> * 设想 :> > * 是否可以有一个专门定义前端页面的地方, 效果可以及时展示,错误可以及时发现,并且可以降低模块间耦合度!> * 解决问题 :模板> > * MVT设计模式中的T,Template> * 在Django中, 将前端的内容定义在模板中, 然后再把模板交给视图调用, 各种漂亮、炫酷的效果就出现了.> ### 模板使用步骤> * 1.创建模板> * 2.设置模板查找路径> * 3.模板接收视图传入的数据> * 4.模板处理数据#### 1.创建模板> * 在应用同级目录下创建模板文件夹templates. 文件夹名称固定写法.> * 在templates文件夹下, 创建应用同名文件夹. 例,Book> * 在应用同名文件夹下创建网页模板文件. 例 :index.html> > > #### 2.设置模板查找路径 #### 3.模板接收视图传入的数据* > 视图模板加载 #### #### 4.模板处理数据 #### 5. 查看模板处理数据成果 总结 展示书籍列表------### 需求 #### 实现步骤> * 1.创建视图> * 2.创建模板> * 3.配置URLconf#### 1.创建视图> * 查询数据库数据> * 构造上下文> * 传递上下文到模板> from django.shortcuts import render from django.http import HttpRequest,HttpResponse from book.models import BookInfo # Create your views here. def index(request): # 实现业务逻辑 # 1、先把所有书籍查询出来 # ORM 实现 books = BookInfo.objects.all() # books = [BookInfo(),] # 2、组织数据 context = { ‘books’:books } # 3、将组织好的数据传递给模板 return render(request,‘index.html’,context)#### 2.创建模板* 读取上下文数据* 构造网页html文档 : 书籍信息以列表样式展示 Title 书籍列表 {% for book in books %} {{ book.name }} {% endfor %} #### 3.配置URLconf* 进入应用中的urls.py文件 from django.urls import path from book.views import index urlpatterns = [ path(‘index/’,index), ]配置和静态文件-------### settings 配置文件#### 1. BASE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file))) 当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。 #### 2. DEBUG调试模式,创建工程后初始值为True,即默认工作在调试模式下。作用:* 修改代码文件,程序自动重启 * Django程序出现异常时,向前端显示详细的错误追踪信息,例如 * 而非调试模式下,仅返回Server Error (500) 注意:部署线上运行的Django不要运行在调式模式下,记得修改DEBUG=False和ALLOW_HOSTS。 #### 3、静态文件项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中,以方便管理。在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。为了提供静态文件,需要配置两个参数:> * STATICFILES_DIRS存放查找静态文件的目录> * STATIC_URL访问静态文件的URL前缀示例1) 在项目根目录下创建static目录来保存静态文件。 2) 在bookmanager/settings.py中修改静态文件的两个参数为 STATIC_URL = ‘/static/’ STATICFILES_DIRS = [ os.path.join(BASE_DIR, ‘static’), ] 3)此时在static添加的任何静态文件都可以使用网址**/static/文件在static中的路径来访问了。 例如,我们向static目录中添加一个index.html文件,在浏览器中就可以使用127.0.0.1:8000/static/index.html来访问。或者我们在static目录中添加了一个子目录和文件book/detail.html,在浏览器中就可以使用127.0.0.1:8000/static/book/detail.html来访问。#### 4、App应用配置 在每个应用目录中都包含了apps.py文件,用于保存该应用的相关信息。在创建应用时,Django会向apps.py文件中写入一个该应用的配置类,如 from django.apps import AppConfig class BookConfig(AppConfig): name = ‘book’ 我们将此类添加到工程settings.py中的INSTALLED_APPS列表中,表明注册安装具备此配置属性的应用。* AppConfig.name属性表示这个配置类是加载到哪个应用的,每个配置类必须包含此属性,默认自动生成。 * AppConfig.verbose_name属性用于设置该应用的直观可读的名字,此名字在Django提供的Admin管理站点中会显示,如 from django.apps import AppConfig class UsersConfig(AppConfig): name = ‘book’ verbose_name = ‘后台相关’ 模型–重点* 模型配置 数据的增删改 * 增:book = BookInfo() book.save()和BookInfo.objects.create() * 删:book.delete()和BookInfo.objects.get().delete() * 改:book.name='xxx' book.save()和BookInfo.objects.get().update(name=xxx) * 数据的查询 * 基础查询 * F对象和Q对象 * 关联查询 * 查询集QuerySet ### 一、项目准备#### 1.创建项目> django-admin startproject bookmanager01> 先设置用户:python manage.py migrate#### 2.创建应用> python manage.py startapp book#### 3. 运行开发服务器> 运行服务器命令:python manage.py runserver ip:端口> > 或:python manage.py runserver#### 4.安装应用 INSTALLED_APPS = [ ‘django.contrib.admin’, ‘django.contrib.auth’, ‘django.contrib.contenttypes’, ‘django.contrib.sessions’, ‘django.contrib.messages’, ‘django.contrib.staticfiles’, #添加子应用 ‘book.apps.BookConfig’ ] #### #### 5.本地化 #设置中文 LANGUAGE_CODE = ‘zh-Hans’ #亚洲上海时区 TIME_ZONE = ‘Asia/Shanghai’ #### 6.创建管理员> 创建管理员命令:python manage.py createsuperuser#### #### 7.模板路径在应用同级目录下,创建templates模板文件夹 TEMPLATES = [ { ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’, ‘DIRS’: [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’, ], }, }, ] #### #### 8.项目中匹配urls正则 : 路径只要不是admin/就算匹配成功。并包含到应用中的urls.py from django.contrib import admin from django.urls import path,include urlpatterns = [ path(‘admin/’, admin.site.urls), path(‘’,include(‘book.urls’)) ] #### #### 9.准备视图 # 定义视图:提供书籍列表信息 def bookList(request): return HttpResponse(‘OK!’) #### #### 10.应用中匹配urls.py> 应用中创建urls.py> > 正则 : 路径中包含booklist/,就调用视图中对应的bookList函数 from django.urls import path from book.views import bookList urlpatterns = [ path(‘booklist/’,bookList), ]#### #### 11.开启服务器, 测试项目> 进入项目文件中, 开启项目对应的服务器 > python manage.py runserver> > 浏览器中输入网址 http://127.0.0.1:8000/booklist/ ### 二、配置数据库在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库。 DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.sqlite3’, ‘NAME’: os.path.join(BASE_DIR, ‘db.sqlite3’), } } #### 1、使用MySQL数据库首先需要安装驱动程序> pip install PyMySQL在Django的工程同名子目录的__init__.py文件中添加如下语句 import pymysql pymysql.install_as_MySQLdb() 作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。1. 修改DATABASES配置信息 # sqlite 主要是一个嵌入式的关系型数据库 # 主要用在移动端 # sqlite 属于小型的关系型数据库 # 中型数据库 mysql(甲骨文) sqlserver(微软) # 大型数据 oracle DB2 DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘HOST’: ‘127.0.0.1’, # 数据库主机 ‘PORT’: ‘3306’, # 数据库端口 ‘USER’: ‘root’, # 数据库用户名 ‘PASSWORD’: ‘123456’, # 数据库用户密码 ‘NAME’: ‘book’, # 数据库名字 } } 1. 在MySQL中创建数据库 > create database book charset=utf8;### 三、定义模型类* 模型类被定义在"应用/models.py"文件中。* 模型类必须继承自Model类,位于包django.db.models中。#### 1 定义在models.py 文件中定义模型类。 from django.db import models # Create your models here. ‘’’ 1、ORM 表 --》 类 字段 --》 属性 2、模型类需要继承models.Model 3、模型类会自动为我们添加(生成)一个主键 4、属性名 = 属性类型(选项) 属性名:不要使用关键,不要使用连续的下划线 属性类型:和mysql的类型相似 选项:charfiled 必须设置 max_length varchar(m) null 是否为空 unique 唯一 default 设置默认值 verbose_name 主要是 admin 后台显示 书籍表: id,name,pub_date,readcount,commentcount,is_delete ‘’’ # 准备书籍列表信息的模型类 class BookInfo(models.Model): # 属性名 = 属性类型(选项) name = models.CharField(10,unique=True,verbose_name=‘名字’) # 发布日期 pub_date = models.DateField(null=True) # 阅读量 readcount = models.IntegerField(default=0) # 评论量 commentcount = models.IntegerField(default=0) # 是否逻辑删除 is_delete = models.BooleanField(default=False) class Meta: # 改表名 db_table = ‘bookinfo’ # 修改后台admin的显示信息的配置 verbose_name = ‘admin’ def str(self): return self.name # 准备人物列表信息的模型类 class PeopleInfo(models.Model): # 有序字典 GENDER_CHOICES = ( (0, ‘male’), (1, ‘female’) ) name = models.CharField(max_length=20, verbose_name=‘名称’) gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name=‘性别’) description = models.CharField(max_length=200, null=True, verbose_name=‘描述信息’) # on_delete 联级 book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name=‘图书’) # 外键 is_delete = models.BooleanField(default=False, verbose_name=‘逻辑删除’) class Meta: db_table = ‘peopleinfo’ verbose_name = ‘人物信息’ def str(self): return self.name##### 1) 数据库表名模型类如果未指明表名,Django默认以小写app应用名_小写模型类名为数据库表名。可通过db_table指明数据库表名。##### 2) 关于主键django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。##### 3) 属性命名限制 不能是python的保留关键字。* 不允许使用连续的下划线,这是由django的查询方式决定的。* 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下: > 属性 = models.字段类型(选项)##### 4)字段类型类型说明AutoField自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性BooleanField布尔字段,值为True或FalseNullBooleanField支持Null、True、False三种值CharField字符串,参数max_length表示最大字符个数TextField大文本字段,一般超过4000个字符时使用IntegerField整数DecimalField十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数FloatField浮点数DateField日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误TimeField时间,参数同DateFieldDateTimeField日期时间,参数同DateFieldFileField上传文件字段ImageField继承于FileField,对上传的内容进行校验,确保是有效的图片##### 5) 选项选项说明null如果为True,表示允许为空,默认值是Falseblank如果为True,则该字段允许为空白,默认值是Falsedb_column字段的名称,如果未指定,则使用属性的名称db_index若值为True, 则在表中会为此字段创建索引,默认值是Falsedefault默认primary_key若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用unique如果为True, 这个字段在表中必须有唯一值,默认值是Falsenull是数据库范畴的概念,blank是表单验证范畴的##### 6) 外键在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:* CASCADE级联,删除主表数据时连通一起删除外键表中数据 * PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据 * SET_NULL设置为NULL,仅在该字段null=True允许为null时可用 * SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用 * SET()设置为特定值或者调用特定方法 * DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常 #### 2 迁移将模型类同步到数据库中。##### 1)生成迁移文件> python manage.py makemigrations##### 2)同步到数据库中> python manage.py migrate#### 3 添加测试数据 insert into bookinfo(name, pub_date, readcount,commentcount, is_delete) values (‘射雕英雄传’, ‘1980-5-1’, 12, 34, 0), (‘天龙八部’, ‘1986-7-24’, 36, 40, 0), (‘笑傲江湖’, ‘1995-12-24’, 20, 80, 0), (‘雪山飞狐’, ‘1987-11-11’, 58, 24, 0); insert into peopleinfo(name, gender, book_id, description, is_delete) values (‘郭靖’, 1, 1, ‘降龙十八掌’, 0), (‘黄蓉’, 0, 1, ‘打狗棍法’, 0), (‘黄药师’, 1, 1, ‘弹指神通’, 0), (‘欧阳锋’, 1, 1, ‘蛤蟆功’, 0), (‘梅超风’, 0, 1, ‘九阴白骨爪’, 0), (‘乔峰’, 1, 2, ‘降龙十八掌’, 0), (‘段誉’, 1, 2, ‘六脉神剑’, 0), (‘虚竹’, 1, 2, ‘天山六阳掌’, 0), (‘王语嫣’, 0, 2, ‘神仙姐姐’, 0), (‘令狐冲’, 1, 3, ‘独孤九剑’, 0), (‘任盈盈’, 0, 3, ‘弹琴’, 0), (‘岳不群’, 1, 3, ‘华山剑法’, 0), (‘东方不败’, 0, 3, ‘葵花宝典’, 0), (‘胡斐’, 1, 4, ‘胡家刀法’, 0), (‘苗若兰’, 0, 4, ‘黄衣’, 0), (‘程灵素’, 0, 4, ‘医术’, 0), (‘袁紫衣’, 0, 4, ‘六合拳’, 0);### 四、shell工具和查看MySQL数据库日志#### 1、shell工具Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试python语句。通过如下命令进入shell> python manage.py shell导入两个模型类,以便后续使用> from book.models import BookInfo,PeopleInfo> > BookInfo.objects.all()### #### 2 查看MySQL数据库日志查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:> vi /etc/mysql/mysql.conf.d/mysqld.cnf把68,69行前面的#去除,然后保存并使用如下命令重启mysql服务。> service mysql restart使用如下命令打开mysql日志文件。> tail -f /var/log/mysql/mysql.log # 可以实时查看数据库的日志内容> > # 如提示需要sudo权限,执行 > # sudo tail -f /var/log/mysql/mysql.log### 五、数据库操作-增、删、改#### 1 增加增加数据有两种方法。##### **1)save(方法一)通过创建模型类对象,执行对象的save()方法保存到数据库中。 from book.models import BookInfo # 方式一 # 会把新生成的对象返回给我们 book = BookInfo( name = ‘python’, pub_date = ‘2010-1-1’ ) # 需要手动待用saver方法 book.save() ##### 2)create(方法二)通过模型类.objects.create()保存。 # 方式二 直接入库 # objects 模型的管理类 # 我们对模型的 增删改查 都用它 BookInfo.objects.create( name = ‘java’, pub_date = ‘2023-1-1’ )#### #### 2 修改修改更新有两种方法##### 1)save(方法一)**修改模型类对象的属性,然后执行save()方法 from book.models import BookInfo # 1、先查询数据 book = BookInfo.objects.get(id = 1) # 2、修改实例属性 book.readcount = 20 # 3、调用save方法 book.save()##### ##### 2)update(方法二)****使用模型类.objects.filter().update(),会返回受影响的行数 # 方法二 直接更新 # filter 过滤 BookInfo.objects.filter(id = 2).update( readcount = 200, commentcount = 300 ) #### 3 删除删除有两种方法##### 1)模型类对象delete # 方法一 # 先查出数据 book = BookInfo.objects.get(name=‘python’) # 调用删除方法 book.delete()##### 2)模型类.objects.filter().delete() BookInfo.objects.filter(name=‘java’).delete() ### 六、数据库操作-查询#### 基础条件查询#### 1 基本查询> get 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常。> > all 查询多个结果。> > count 查询结果数量。 # get 得到某一个数据 # all 获取所有的 # count 个数 from book.models import BookInfo # get返回一个对象 book = BookInfo.objects.get(id=1) # 查询不存在的数据会抛出异常 # 完美写法 try: book = BookInfo.objects.get(id=2) except BookInfo.DoesNotExist: pass # all 返回所有结果是列表 BookInfo.objects.all() # count BookInfo.objects.all().count() BookInfo.objects.count()#### #### 2 过滤查询实现SQL中的where功能,包括> filter 过滤出多个结果> > exclude 排除掉符合条件剩下的结果> > get 过滤单一结果对于过滤条件的使用,上述三个方法相同,故仅以filter进行讲解。过滤条件的表达语法如下:> # 语法形式: filter(属性名称__比较运算符 = 值)> # 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线##### 1)相等exact:表示判等。**例:查询编号为1的图书。 BookInfo.objects.get(id__exact = 1) # exact 精确的 就是等于 BookInfo.objects.get(id= 1) BookInfo.objects.filter(id=1) BookInfo.objects.filter(id__exact = 1) ##### **2)模糊查询contains:是否包含。> 说明:如果要包含%无需转义,直接写即可。例:查询书名包含’湖’的图书。 # 查询书名包含’湖’的图书 # contains 包含 BookInfo.objects.filter(name__contains=‘湖’) **startswith、endswith:以指定值开头或结尾。**例:查询书名以’部’结尾的图书 # 查询书名以’部’结尾的图书 BookInfo.objects.filter(name__endswith=‘部’) > 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith##### **3) 空查询isnull:是否为null。**例:查询书名为空的图书。 # 查询书名为空的图书 BookInfo.objects.filter(name__isnull=True)##### ##### **4) 范围查询in:是否包含在范围内。**例:查询编号为1或3或5的图书 # 查询编号为1或3或5的图书 BookInfo.objects.filter(id__in=[1,3,5]) ##### 5)比较查询> gt 大于 (greater then)> > gte大于等于 (greater then equal)> > lt 小于 (less then)> > lte 小于等于 (less then equal)例:查询编号大于3的图书 BookInfo.objects.filter(id__gt=3) **不等于的运算符,使用exclude()过滤器。*例:查询编号不等于3的图书 # 查询编号不等于3的图书 BookInfo.objects.exclude(id=3) ##### 6)日期查询****year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。例:查询1980年发表的图书。 # 查询1980年发表的图书 BookInfo.objects.filter(pub_date__year=1980) 例:查询1990年1月1日后发表的图书。 # 查询1990年1月1日后发表的图书 BookInfo.objects.filter(pub_date__gt=‘1990-1-1’) 注意事项 #### 3、F和Q对象##### F对象之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢?答:使用F对象,被定义在django.db.models中。> 语法: F(属性名)例:查询阅读量大于等于评论量的图书。 # 查询阅读量大于等于评论量的图书 from django.db.models import F BookInfo.objects.filter(readcount__gt=F(‘commentcount’)) 可以在F对象上使用算数运算。例:查询阅读量大于2倍评论量的图书。 # 查询阅读量大于2倍评论量的图书 BookInfo.objects.filter(readcount__gt=F(‘commentcount’)*2) ##### Q对象多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。例:查询阅读量大于20,并且编号小于3的图书。 # 查询阅读量大于20,并且编号小于3的图书。 BookInfo.objects.filter(readcount__gt=20,id__lt=3) BookInfo.objects.filter(readcount__gt=20).filter(id__lt=3) 如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被义在django.db.models中。> 语法: Q(属性名__运算符=值)例:查询阅读量大于20的图书,改写为Q对象如下。 # 查询阅读量大于20的图书,改写为Q对象如下。 from django.db.models import Q BookInfo.objects.filter(Q(readcount__gt=20)) Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现 # 查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现 BookInfo.objects.filter(Q(readcount__gt=20)|Q(id__lt=3)) Q对象前可以使用~操作符,表示非not。例:查询编号不等于3的图书。 # 查询编号不等于3的图书。 BookInfo.objects.filter(~Q(id=3)) #### 4、聚合函数和排序函数##### 1. 聚合函数使用aggregate()过滤器调用聚合函数。聚合函数包括:Avg平均,Count数量,Max最大,Min最小,Sum求和,被定义在django.db.models中。例:查询图书的总阅读量。 from django.db.models import Sum # 查询图书的总阅读量。 BookInfo.objects.aggregate(Sum(‘readcount’)) 注意aggregate的返回值是一个字典类型,格式如下:> {‘属性名__聚合类小写’:值}> > 如:{‘readcount__sum’: 298}使用count时一般不使用aggregate()过滤器。例:查询图书总数。 # 查询图书总数。 BookInfo.objects.count() 注意count函数的返回值是一个数字。##### 2. 排序使用order_by对结果进行排序 # 默认升序 BookInfo.objects.all().order_by(‘readcount’) # 降序 BookInfo.objects.all().order_by(‘-readcount’) #### 5、关联查询> 查询书籍为1的所有人物信息 > 查询人物为1的书籍信息由一到多的访问语法:> 一对一的模型类对象.多对一的模型类名小写_set例: # 查询书籍为1的所有人物信息 ==》 通过书籍 查询人物 # 查询书籍 book = BookInfo.objects.get(id=1) # 根据书籍关联人物信息 book.peopleinfo_set.all() 由多到一的访问语法:> 多对应的模型类对象.多对应的模型类中的关系类属性名例: # 查询人物为1的书籍信息 ==》 根据书籍查询人物 from book.models import PeopleInfo # 1、查询人物 person = PeopleInfo.objects.get(id=1) # 2、根据人物关联查询数据 person.book person.book.name person.book.readcount person 访问一对一的模型类关联对象的id语法:> 多对一的模型类对象.关联类属性_id例: person = PeopleInfo.objects.get(id=1) person.book_id ##### ##### 关联过滤查询由多模型类条件查询一模型类数据:语法如下:> 关联模型类名小写__属性名__条件运算符=值> 注意:如果没有"__运算符"部分,表示等于。例:查询图书,要求图书人物为"郭靖" book = BookInfo.objects.filter(peopleinfo__name=‘郭靖’) book 查询图书,要求图书中人物的描述包含"八" book = BookInfo.objects.filter(peopleinfo__description__contains=‘八’) book 由一模型类条件查询多模型类数据:语法如下:> 一模型类关联属性名__一模型类属性名__条件运算符=值> 注意:如果没有"__运算符"部分,表示等于。例:查询书名为“天龙八部”的所有人物。 # 查询书名为“天龙八部”的所有人物。 people = PeopleInfo.objects.filter(book__name=‘天龙八部’) people 查询图书阅读量大于30的所有人物 # 查询图书阅读量大于30的所有人物 people = PeopleInfo.objects.filter(book__readcount__gt=30) people #### 6、查询集QuerySet##### 1 概念Django的ORM中存在查询集的概念。查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):> all() 返回所有数据。> > filter() 返回满足条件的数据。> > exclude() 返回满足条件之外的数据。> > order_by()对结果进行排序。对查询集可以再次调用过滤器进行过滤,如 books = BookInfo.objects.filter(readcount__gt=30).order_by(‘pub_date’) books 也就意味着查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果。从SQL的角度讲,查询集与select语句等价,过滤器像where、limit、order by子句。**判断某一个查询集中是否有数据:> exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。##### 2 两大特性1)惰性执行创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集books books = BookInfo.objects.all() 继续执行遍历迭代操作后,才真正的进行了数据库的查询 for book in books: print(book.name) 2)缓存使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。情况一:如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。 from book.models import BookInfo [book.id for book in BookInfo.objects.all()] [book.id for book in BookInfo.objects.all()] # 上面写发没有使用缓存 情况二:经过存储后,可以重用查询集,第二次使用缓存中的数据。 # 优化后的代码 books=BookInfo.objects.all() [book.id for book in books] [book.id for book in books]##### ##### 3 限制查询集可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。> 注意:不支持负数索引。对查询集进行切片后返回一个新的查询集,不会立即执行查询。如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()如果没有数据引发DoesNotExist异常。示例:获取第1、2项,运行查看。 # 获取前两条数据 books = BookInfo.objects.all()[0:2] books = BookInfo.objects.all()[:2] # 和上面写发一样 books ##### 4 分页 #查询数据 books = BookInfo.objects.all() #导入分页类 from django.core.paginator import Paginator #创建分页实例 paginator=Paginator(books,2) #获取指定页码的数据 page_skus = paginator.page(1) #获取分页数据 total_page=paginator.num_pages视图–重点 HttpRequest * 位置参数和关键字参数 * 查询字符串 * 请求体:表单数据,JSON数据 * 请求头 HttpResponse * HttpResponse * JsonResponse * redirect * 类视图 * 类视图的定义和使用 * 类视图装饰器(难点) 一、视图介绍和项目准备----------- ##### 视图介绍> * 视图就是应用中views.py文件中的函数> * 视图的第一个参数必须为HttpRequest对象,还可能包含下参数如> * 通过正则表达式组获取的位置参数> * 通过正则表达式组获得的关键字参数> * 视图必须返回一个HttpResponse对象或子对象作为响应> * 子对象:JsonResponseHttpResponseRedirect> * 视图负责接受Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者> * 响应内容可以是HTML内容,404错误,重定向,json数据…> * 视图处理过程如下图:> > > > 使用视图时需要进行两步操作,两步操作不分先后> > 1. 配置URLconf> 2. 在应用/views.py中定义视图##### 项目准备 创建项目+创建应用+安装应用+配置模板路径+本地化+mysql数据库+URLconf+视图 * 安装应用 INSTALLED_APPS = [ ‘django.contrib.admin’, ‘django.contrib.auth’, ‘django.contrib.contenttypes’, ‘django.contrib.sessions’, ‘django.contrib.messages’, ‘django.contrib.staticfiles’, ‘book.apps.BookConfig’ ] mysql数据库使用之前的book DATABASES = { ‘default’: { ‘ENGINE’: ‘django.db.backends.mysql’, ‘HOST’: ‘127.0.0.1’, # 数据库主机 ‘PORT’: 3306, # 数据库端口 ‘USER’: ‘root’, # 数据库用户名 ‘PASSWORD’: ‘mysql’, # 数据库用户密码 ‘NAME’: ‘book’ # 数据库名字 } } URLconf * settings.py中:指定url配置 ROOT_URLCONF = ‘bookmanager01.urls’ TEMPLATES = [ { ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’, ‘DIRS’: [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’, ], }, }, ] * 项目中urls.py:只要不是admin/就匹配成功,包含到应用中的urls.py from django.contrib import admin from django.urls import path,include urlpatterns = [ path(‘admin/’, admin.site.urls), path(‘’,include(‘book.urls’)) ] * 应用中urls.py:匹配testproject/成功就调用views中的testproject函数,测试项目逻辑 from django.conf.urls import url import views urlpatterns = [ # 匹配testproject/成功就调用views中的testproject函数 url(r’^testproject/KaTeX parse error: Expected 'EOF', got '#' at position 279: … #̲ 测试项目逻辑 …‘,index), # 匹配书籍列表信息的URL,调用对应的bookList视图 url(r’^booklist/ ′ , b o o k L i s t , n a m e = ′ i n d e x ′ ) , u r l ( r ′ t e s t p r o j e c t / ',bookList,name='index'), url(r'^testproject/ ′,bookList,name=′index′),url(r′testproject/‘,views.testproject,name=‘test’), ] ### 2 reverse反解析(通过名字找到路由)使用reverse函数,可以根据路由名称,返回具体的路径,如: from django.core.urlresolvers import reverse #或者 from django.urls import reverse def testproject(request): return HttpResponse(“OK”) # 定义视图:提供书籍列表信息 def bookList(request): url = reverse(‘book:test’) print(url) return HttpResponse(‘index’) > * 对于未指明namespace的,reverse(路由name)> * 对于指明namespace的,reverse(命名空间namespace:路由name)> > > > 四、HttpRequest对象---------------利用HTTP协议向服务器传参有几种途径?> * 提取URL的特定部分,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取;> * 查询字符串(query string),形如key1=value1&key2=value2;> * 请求体(body)中发送的数据,比如表单数据、json、xml;> * 在http报文的头(header)中。### 1 URL路径参数> * 如果想从URL中获取值,需要在正则表达式中使用分组,> * 获取值分为两种方式> * 位置参数> * 参数的位置不能错> * 关键字参数> * 参数的位置可以变,跟关键字保持一致即可> * 注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式> * 分别使用以上两种获取URL值的方式提取出18 188> * http://127.0.0.1:8000/18/188/ 位置参数(推荐使用)> * 应用中urls.py> > urlpatterns = [> path(‘booklist/’,bookList),> > url(r’^(d+)/(d+)/KaTeX parse error: Expected 'EOF', got '#' at position 535: … > #̲ 位置参数> …‘,detail),> # 关键字参数> url(r’^(?Pd+)/(?Pd+)/KaTeX parse error: Expected 'EOF', got '#' at position 298: …0d35edaeb5.png)#̲## 2 Django中的Qu…‘, views.register, name=‘register’), # 类视图:注册 url(r’^register/KaTeX parse error: Expected 'EOF', got '#' at position 288: …t), #̲ 位置参数 # …‘,detail), # 关键字参数 url(r’^(?Pd+)/(?Pd+)/KaTeX parse error: Expected 'EOF', got '#' at position 621: …ponse('个人中心修改')#̲## 2、中间件Django中…‘,views.LoginView.as_view(),name=‘index’), #登录路由 url(r’^transfer/KaTeX parse error: Expected 'EOF', got '#' at position 50: …e='transfer'), #̲转账路由 ] …',views.AdsView.as_view()), ] #定义视图 class AdsView(View): def get(self,request): return render(request,‘index.html’) * 前端代码实现 Title 我是网站B > 运行测试,在用户登录网站A的情况下,点击网站B的按钮,可以实现伪造访问#### 在网站A中实现 csrf_token 校验的流程 导入生成 csrf_token 的函数 from django.middleware.csrf import get_token csrf_token = get_token(request) * 在渲染转账页面的,做以下几件事情: 1. 生成 csrf_token 的值 2. 在返回转账页面的响应里面设置 csrf_token 到 cookie 中 3. 将 csrf_token 保存到表单的隐藏字段中 def get(self, request): # 生成csrf_token from django.middleware.csrf import get_token csrf_token = get_token(request) # 渲染转换页面,传入 csrf_token 到模板中 response = render(request, ‘transfer.html’,context={‘csrf_token’:csrf_token}) # 设置csrf_token到cookie中,用于提交校验 response.set_cookie(‘csrf_token’, csrf_token) return response * 在转账模板表单中添加 csrf_token 隐藏字段 转账 我是网站A,转账页面 账户: 金额: 运行测试,进入到转账页面之后,查看 cookie 和 html 源代码 在执行转账逻辑之前进行 csrf_token 的校验 # 取出表单中的 csrf_token form_csrf_token = request.POST.get(“csrftoken”) # 取出 cookie 中的 csrf_token cookie_csrf_token = request.COOKIES.get(‘csrf_token’) # 进行对比 if cookie_csrf_token != form_csrf_token: return HttpResponse(‘token校验失败,可能是非法操作’) 运行测试,用户直接在网站 A 操作没有问题,再去网站B进行操作,发现转账不成功,因为网站 B 获取不到表单中的 csrf_token 的隐藏字段,而且浏览器有同源策略,网站B是获取不到网站A的 cookie 的,所以就解决了跨站请求伪造的问题### 在 Django项目中解决 CSRF 攻击Django默认是开启CSRF的 模板中设置 CSRF 令牌 {% csrf_token %} 或者)
- {% for book in books %}
- {{ book.name }}
- {% endfor %}
3.配置URLconf* 进入应用中的urls.py文件 from django.urls import path from book.views import index urlpatterns = path('index/',index), 配置和静态文件-------### settings 配置文件#### 1. BASE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file ))) 当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。
#### 2. DEBUG调试模式,创建工程后初始值为True ,即默认工作在调试模式下。作用:* 修改代码文件,程序自动重启 * Django程序出现异常时,向前端显示详细的错误追踪信息,例如
* 而非调试模式下,仅返回Server Error (500) 注意:部署线上运行的Django不要运行在调式模式下,记得修改DEBUG=False和ALLOW_HOSTS。
#### 3、静态文件项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中,以方便管理。在html页面中调用时,也需要指定静态文件的路径,Django中提供了一种解析的方式配置静态文件路径。静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。为了提供静态文件,需要配置两个参数:> * STATICFILES_DIRS 存放查找静态文件的目录> * STATIC_URL 访问静态文件的URL前缀示例 1) 在项目根目录下创建static目录来保存静态文件。
2) 在bookmanager/settings.py中修改静态文件的两个参数为 STATIC_URL = '/static/' STATICFILES_DIRS = os.path.join(BASE_DIR, 'static'), 3)此时在static添加的任何静态文件都可以使用网址**/static/文件在static中的路径来访问了。
例如,我们向static目录中添加一个index.html文件,在浏览器中就可以使用127.0.0.1:8000/static/index.html来访问。或者我们在static目录中添加了一个子目录和文件book/detail.html,在浏览器中就可以使用127.0.0.1:8000/static/book/detail.html来访问。#### 4、App应用配置
在每个应用目录中都包含了apps.py文件,用于保存该应用的相关信息。在创建应用时,Django会向apps.py文件中写入一个该应用的配置类,如 from django.apps import AppConfig class BookConfig(AppConfig): name = 'book' 我们将此类添加到工程settings.py中的INSTALLED_APPS列表中,表明注册安装具备此配置属性的应用。* AppConfig.name 属性表示这个配置类是加载到哪个应用的,每个配置类必须包含此属性,默认自动生成。 * AppConfig.verbose_name 属性用于设置该应用的直观可读的名字,此名字在Django提供的Admin管理站点中会显示,如 from django.apps import AppConfig class UsersConfig(AppConfig): name = 'book' verbose_name = '后台相关' 

模型--重点* 模型配置 数据的增删改 * 增:book = BookInfo() book.save()和BookInfo.objects.create() * 删:book.delete()和BookInfo.objects.get().delete() * 改:book.name='xxx' book.save()和BookInfo.objects.get().update(name=xxx) * 数据的查询 * 基础查询 * F对象和Q对象 * 关联查询 * 查询集QuerySet
### 一、项目准备#### 1.创建项目> django-admin startproject bookmanager01 > 先设置用户:python manage.py migrate #### 2.创建应用> python manage.py startapp book #### 3. 运行开发服务器> 运行服务器命令:python manage.py runserver ip:端口 > > 或:python manage.py runserver #### 4.安装应用 INSTALLED_APPS = 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', #添加子应用 'book.apps.BookConfig' ####
#### 5.本地化 #设置中文 LANGUAGE_CODE = 'zh-Hans' #亚洲上海时区 TIME_ZONE = 'Asia/Shanghai'
#### 6.创建管理员> 创建管理员命令:python manage.py createsuperuser ####
#### 7.模板路径在应用同级目录下,创建templates模板文件夹 TEMPLATES = { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': \[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', , }, }, ] ####
#### 8.项目中匹配urls正则 : 路径只要不是admin/就算匹配成功。并包含到应用中的urls.py from django.contrib import admin from django.urls import path,include urlpatterns = path('admin/', admin.site.urls), path('',include('book.urls')) ####
#### 9.准备视图 # 定义视图:提供书籍列表信息 def bookList(request): return HttpResponse('OK!') ####
#### 10.应用中匹配urls.py> 应用中创建urls.py> > 正则 : 路径中包含booklist/,就调用视图中对应的bookList函数 from django.urls import path from book.views import bookList urlpatterns = path('booklist/',bookList), ####
#### 11.开启服务器, 测试项目> 进入项目文件中, 开启项目对应的服务器 > python manage.py runserver > > 浏览器中输入网址 http://127.0.0.1:8000/booklist/### 二、配置数据库在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用* sqlite 数据库。 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } #### 1、使用 MySQL 数据库首先需要安装驱动程序> pip install PyMySQL在Django的工程同名子目录的__init__.py文件中添加如下语句 import pymysql pymysql.install_as_MySQLdb()
作用是让Django的ORM能以mysqldb的方式来调用PyMySQL。1. 修改 DATABASES 配置信息 # sqlite 主要是一个嵌入式的关系型数据库 # 主要用在移动端 # sqlite 属于小型的关系型数据库 # 中型数据库 mysql(甲骨文) sqlserver(微软) # 大型数据 oracle DB2 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 数据库主机 'PORT': '3306', # 数据库端口 'USER': 'root', # 数据库用户名 'PASSWORD': '123456', # 数据库用户密码 'NAME': 'book', # 数据库名字 } }
1. 在MySQL中创建数据库 > create database book charset=utf8;### 三、定义模型类* 模型类被定义在"应用/models.py"文件中。* 模型类必须继承自Model类,位于包django.db.models中。#### 1 定义在models.py 文件中定义模型类。 from django.db import models # Create your models here. ''' 1、ORM 表 --》 类 字段 --》 属性 2、模型类需要继承models.Model 3、模型类会自动为我们添加(生成)一个主键 4、属性名 = 属性类型(选项) 属性名:不要使用关键,不要使用连续的下划线 属性类型:和mysql的类型相似 选项:charfiled 必须设置 max_length varchar(m) null 是否为空 unique 唯一 default 设置默认值 verbose_name 主要是 admin 后台显示 书籍表: id,name,pub_date,readcount,commentcount,is_delete ''' # 准备书籍列表信息的模型类 class BookInfo(models.Model): # 属性名 = 属性类型(选项) name = models.CharField(10,unique=True,verbose_name='名字') # 发布日期 pub_date = models.DateField(null=True) # 阅读量 readcount = models.IntegerField(default=0) # 评论量 commentcount = models.IntegerField(default=0) # 是否逻辑删除 is_delete = models.BooleanField(default=False) class Meta: # 改表名 db_table = 'bookinfo' # 修改后台admin的显示信息的配置 verbose_name = 'admin' def str (self): return self.name # 准备人物列表信息的模型类 class PeopleInfo(models.Model): # 有序字典 GENDER_CHOICES = ( (0, 'male'), (1, 'female') ) name = models.CharField(max_length=20, verbose_name='名称') gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别') description = models.CharField(max_length=200, null=True, verbose_name='描述信息') # on_delete 联级 book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键 is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'peopleinfo' verbose_name = '人物信息' def str (self): return self.name##### 1) 数据库表名模型类如果未指明表名,Django默认以 小写app应用名_小写模型类名 为数据库表名。可通过 db_table 指明数据库表名。##### 2) 关于主键 django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。##### 3) 属性命名限制 不能是python的保留关键字。* 不允许使用连续的下划线,这是由django的查询方式决定的。* 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下: > 属性 = models.字段类型(选项) ##### 4)字段类型 类型说明AutoField自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性BooleanField布尔字段,值为True或FalseNullBooleanField支持Null、True、False三种值CharField字符串,参数max_length表示最大字符个数TextField大文本字段,一般超过4000个字符时使用IntegerField整数DecimalField十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数FloatField浮点数DateField日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误TimeField时间,参数同DateFieldDateTimeField日期时间,参数同DateFieldFileField上传文件字段ImageField继承于FileField,对上传的内容进行校验,确保是有效的图片##### 5) 选项 选项说明null如果为True,表示允许为空,默认值是Falseblank如果为True,则该字段允许为空白,默认值是Falsedb_column字段的名称,如果未指定,则使用属性的名称db_index若值为True, 则在表中会为此字段创建索引,默认值是Falsedefault默认primary_key若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用unique如果为True, 这个字段在表中必须有唯一值,默认值是Falsenull是数据库范畴的概念,blank是表单验证范畴的* ##### 6) 外键 在设置外键时,需要通过on_delete 选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:* CASCADE 级联,删除主表数据时连通一起删除外键表中数据 * PROTECT 保护,通过抛出ProtectedError 异常,来阻止删除主表中被外键应用的数据 * SET_NULL 设置为NULL,仅在该字段null=True允许为null时可用 * SET_DEFAULT 设置为默认值,仅在该字段设置了默认值时可用 * SET()设置为特定值或者调用特定方法 * DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError 异常 #### 2 迁移将模型类同步到数据库中。##### 1)生成迁移文件 > python manage.py makemigrations ##### 2)同步到数据库中 > python manage.py migrate #### 3 添加测试数据 insert into bookinfo(name, pub_date, readcount,commentcount, is_delete) values ('射雕英雄传', '1980-5-1', 12, 34, 0), ('天龙八部', '1986-7-24', 36, 40, 0), ('笑傲江湖', '1995-12-24', 20, 80, 0), ('雪山飞狐', '1987-11-11', 58, 24, 0); insert into peopleinfo(name, gender, book_id, description, is_delete) values ('郭靖', 1, 1, '降龙十八掌', 0), ('黄蓉', 0, 1, '打狗棍法', 0), ('黄药师', 1, 1, '弹指神通', 0), ('欧阳锋', 1, 1, '蛤蟆功', 0), ('梅超风', 0, 1, '九阴白骨爪', 0), ('乔峰', 1, 2, '降龙十八掌', 0), ('段誉', 1, 2, '六脉神剑', 0), ('虚竹', 1, 2, '天山六阳掌', 0), ('王语嫣', 0, 2, '神仙姐姐', 0), ('令狐冲', 1, 3, '独孤九剑', 0), ('任盈盈', 0, 3, '弹琴', 0), ('岳不群', 1, 3, '华山剑法', 0), ('东方不败', 0, 3, '葵花宝典', 0), ('胡斐', 1, 4, '胡家刀法', 0), ('苗若兰', 0, 4, '黄衣', 0), ('程灵素', 0, 4, '医术', 0), ('袁紫衣', 0, 4, '六合拳', 0);### 四、shell工具和查看MySQL数据库日志#### 1、shell工具Django的manage工具提供了shell 命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试python语句。通过如下命令进入shell> python manage.py shell 导入两个模型类,以便后续使用> from book.models import BookInfo,PeopleInfo > > BookInfo.objects.all() ###
#### 2 查看MySQL数据库日志查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:> vi /etc/mysql/mysql.conf.d/mysqld.cnf 把68,69行前面的#去除,然后保存并使用如下命令重启mysql服务。> service mysql restart 使用如下命令打开mysql日志文件。> tail -f /var/log/mysql/mysql.log # 可以实时查看数据库的日志内容> > # 如提示需要sudo权限,执行 > # sudo tail -f /var/log/mysql/mysql.log### 五、数据库操作-增、删、改#### 1 增加增加数据有两种方法。##### **1)save(方法一)通过创建模型类对象,执行对象的save()方法保存到数据库中。 from book.models import BookInfo # 方式一 # 会把新生成的对象返回给我们 book = BookInfo( name = 'python', pub_date = '2010-1-1' ) # 需要手动待用saver方法 book.save()
##### 2)create(方法二)通过模型类.objects.create()保存。 # 方式二 直接入库 # objects 模型的管理类 # 我们对模型的 增删改查 都用它 BookInfo.objects.create( name = 'java', pub_date = '2023-1-1' )####
#### 2 修改修改更新有两种方法##### 1)save(方法一)**修改模型类对象的属性,然后执行save()方法 from book.models import BookInfo # 1、先查询数据 book = BookInfo.objects.get(id = 1) # 2、修改实例属性 book.readcount = 20 # 3、调用save方法 book.save()#####
##### 2)update(方法二)****使用模型类.objects.filter().update() ,会返回受影响的行数 # 方法二 直接更新 # filter 过滤 BookInfo.objects.filter(id = 2).update( readcount = 200, commentcount = 300 )
#### 3 删除删除有两种方法##### 1)模型类对象delete # 方法一 # 先查出数据 book = BookInfo.objects.get(name='python') # 调用删除方法 book.delete()##### 2)模型类.objects.filter().delete() BookInfo.objects.filter(name='java').delete()
### 六、数据库操作-查询#### 基础条件查询#### 1 基本查询> get 查询单一结果,如果不存在会抛出模型类.DoesNotExist 异常。> > all 查询多个结果。> > count 查询结果数量。 # get 得到某一个数据 # all 获取所有的 # count 个数 from book.models import BookInfo # get返回一个对象 book = BookInfo.objects.get(id=1) # 查询不存在的数据会抛出异常 # 完美写法 try: book = BookInfo.objects.get(id=2) except BookInfo.DoesNotExist: pass # all 返回所有结果是列表 BookInfo.objects.all() # count BookInfo.objects.all().count() BookInfo.objects.count()#### 

#### 2 过滤查询实现SQL中的where功能,包括> filter 过滤出多个结果> > exclude 排除掉符合条件剩下的结果> > get 过滤单一结果对于过滤条件的使用,上述三个方法相同,故仅以filter 进行讲解。过滤条件的表达语法如下:> # 语法形式: filter(属性名称__比较运算符 = 值)> # 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线 ##### 1)相等exact:表示判等。**例:查询编号为1的图书。 BookInfo.objects.get(id__exact = 1) # exact 精确的 就是等于 BookInfo.objects.get(id= 1) BookInfo.objects.filter(id=1) BookInfo.objects.filter(id__exact = 1)
##### **2)模糊查询contains:是否包含。 > 说明:如果要包含%无需转义,直接写即可。例:查询书名包含'湖'的图书。 # 查询书名包含'湖'的图书 # contains 包含 BookInfo.objects.filter(name__contains='湖')
**startswith、endswith:以指定值开头或结尾。**例:查询书名以'部'结尾的图书 # 查询书名以'部'结尾的图书 BookInfo.objects.filter(name__endswith='部')
> 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith##### **3) 空查询isnull:是否为null。**例:查询书名为空的图书。 # 查询书名为空的图书 BookInfo.objects.filter(name__isnull=True)#####
##### **4) 范围查询 in:是否包含在范围内。**例:查询编号为1或3或5的图书 # 查询编号为1或3或5的图书 BookInfo.objects.filter(id__in=1,3,5)
##### 5)比较查询 > gt 大于 (greater then)> > gte 大于等于 (greater then equal)> > lt 小于 (less then)> > lte 小于等于 (less then equal)例:查询编号大于3的图书 BookInfo.objects.filter(id__gt=3)
**不等于的运算符,使用exclude()过滤器。**例:查询编号不等于3的图书 # 查询编号不等于3的图书 BookInfo.objects.exclude(id=3)
##### **6)日期查询****year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。**例:查询1980年发表的图书。 # 查询1980年发表的图书 BookInfo.objects.filter(pub_date__year=1980)
例:查询1990年1月1日后发表的图书。 # 查询1990年1月1日后发表的图书 BookInfo.objects.filter(pub_date__gt='1990-1-1')
注意事项
#### 3、F和Q对象##### F对象之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢?答:使用F对象,被定义在django.db.models中。> 语法: F(属性名)例:查询阅读量大于等于评论量的图书。 # 查询阅读量大于等于评论量的图书 from django.db.models import F BookInfo.objects.filter(readcount__gt=F('commentcount'))
可以在F对象上使用算数运算。例:查询阅读量大于2倍评论量的图书。 # 查询阅读量大于2倍评论量的图书 BookInfo.objects.filter(readcount__gt=F('commentcount')*2)
##### Q对象 多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。例:查询阅读量大于20,并且编号小于3的图书。 # 查询阅读量大于20,并且编号小于3的图书。 BookInfo.objects.filter(readcount__gt=20,id__lt=3) BookInfo.objects.filter(readcount__gt=20).filter(id__lt=3)
如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符 ,Q对象被义在django.db.models中。 > 语法: Q(属性名__运算符=值)例:查询阅读量大于20的图书,改写为Q对象如下。 # 查询阅读量大于20的图书,改写为Q对象如下。 from django.db.models import Q BookInfo.objects.filter(Q(readcount__gt=20))
Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现 # 查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现 BookInfo.objects.filter(Q(readcount__gt=20)|Q(id__lt=3))
Q对象前可以使用~操作符,表示非not。例:查询编号不等于3的图书。 # 查询编号不等于3的图书。 BookInfo.objects.filter(~Q(id=3))
#### 4、聚合函数和排序函数##### 1. 聚合函数使用aggregate()过滤器调用聚合函数。聚合函数包括:Avg 平均,Count 数量,Max 最大,Min 最小,Sum 求和,被定义在django.db.models中。例:查询图书的总阅读量。 from django.db.models import Sum # 查询图书的总阅读量。 BookInfo.objects.aggregate(Sum('readcount'))
注意aggregate的返回值是一个字典类型,格式如下:> {'属性名__聚合类小写':值} > > 如:{'readcount__sum': 298}使用count时一般不使用aggregate()过滤器。例:查询图书总数。 # 查询图书总数。 BookInfo.objects.count()
注意count函数的返回值是一个数字。##### 2. 排序使用order_by 对结果进行排序 # 默认升序 BookInfo.objects.all().order_by('readcount') # 降序 BookInfo.objects.all().order_by('-readcount')
#### 5、关联查询> 查询书籍为1的所有人物信息 > 查询人物为1的书籍信息由一到多的访问语法:> 一对一的模型类对象.多对一的模型类名小写_set例: # 查询书籍为1的所有人物信息 ==》 通过书籍 查询人物 # 查询书籍 book = BookInfo.objects.get(id=1) # 根据书籍关联人物信息 book.peopleinfo_set.all()
由多到一的访问语法:> 多对应的模型类对象.多对应的模型类中的关系类属性名例: # 查询人物为1的书籍信息 ==》 根据书籍查询人物 from book.models import PeopleInfo # 1、查询人物 person = PeopleInfo.objects.get(id=1) # 2、根据人物关联查询数据 person.book person.book.name person.book.readcount person
访问一对一的模型类关联对象的id语法:> 多对一的模型类对象.关联类属性_id例: person = PeopleInfo.objects.get(id=1) person.book_id
#####
##### 关联过滤查询由多模型类条件查询一模型类数据 :语法如下:> 关联模型类名小写__属性名__条件运算符=值 > **注意:如果没有"__运算符"部分,表示等于。**例:查询图书,要求图书人物为"郭靖" book = BookInfo.objects.filter(peopleinfo__name='郭靖') book
查询图书,要求图书中人物的描述包含"八" book = BookInfo.objects.filter(peopleinfo__description__contains='八') book
由一模型类条件查询多模型类数据 :语法如下:> 一模型类关联属性名__一模型类属性名__条件运算符=值 > *注意:如果没有"__运算符"部分,表示等于。例:查询书名为"天龙八部"的所有人物。 # 查询书名为"天龙八部"的所有人物。 people = PeopleInfo.objects.filter(book__name='天龙八部') people
查询图书阅读量大于30的所有人物 # 查询图书阅读量大于30的所有人物 people = PeopleInfo.objects.filter(book__readcount__gt=30) people
#### 6、查询集QuerySet##### 1 概念Django的ORM中存在查询集的概念。查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):> all() 返回所有数据。> > filter() 返回满足条件的数据。> > exclude() 返回满足条件之外的数据。> > order_by()对结果进行排序。对查询集可以再次调用过滤器进行过滤,如 books = BookInfo.objects.filter(readcount__gt=30).order_by('pub_date') books
也就意味着查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果。从SQL的角度讲,查询集与select语句等价,过滤器像where、limit、order by子句。**判断某一个查询集中是否有数据:> exists():判断查询集中是否有数据,如果有则返回True,没有则返回False。##### 2 两大特性1)惰性执行 创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集books books = BookInfo.objects.all() 继续执行遍历迭代操作后,才真正的进行了数据库的查询 for book in books: print(book.name)
2)缓存 使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。情况一 :如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。 from book.models import BookInfo book.id for book in BookInfo.objects.all() book.id for book in BookInfo.objects.all() # 上面写发没有使用缓存
情况二 :经过存储后,可以重用查询集,第二次使用缓存中的数据。 # 优化后的代码 books=BookInfo.objects.all() book.id for book in books book.id for book in books#####
##### 3 限制查询集可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。> 注意:不支持负数索引。对查询集进行切片后返回一个新的查询集,不会立即执行查询。如果获取一个对象,直接使用0,等同于0:1.get(),但是如果没有数据,0引发IndexError异常,0:1.get()如果没有数据引发DoesNotExist异常。示例:获取第1、2项,运行查看。 # 获取前两条数据 books = BookInfo.objects.all()0:2 books = BookInfo.objects.all():2 # 和上面写发一样 books
##### 4 分页 #查询数据 books = BookInfo.objects.all() #导入分页类 from django.core.paginator import Paginator #创建分页实例 paginator=Paginator(books,2) #获取指定页码的数据 page_skus = paginator.page(1) #获取分页数据 total_page=paginator.num_pages视图--重点 HttpRequest * 位置参数和关键字参数 * 查询字符串 * 请求体:表单数据,JSON数据 * 请求头 HttpResponse * HttpResponse * JsonResponse * redirect * 类视图 * 类视图的定义和使用 * 类视图装饰器(难点) 一、视图介绍和项目准备-----------
##### 视图介绍> * 视图就是应用中views.py文件中的函数> * 视图的第一个参数必须为HttpRequest对象,还可能包含下参数如> * 通过正则表达式组获取的位置参数> * 通过正则表达式组获得的关键字参数> * 视图必须返回一个HttpResponse对象或子对象作为响应> * 子对象:JsonResponse``HttpResponseRedirect> * 视图负责接受Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者> * 响应内容可以是HTML内容,404错误,重定向,json数据...> * 视图处理过程如下图:> > >
> 使用视图时需要进行两步操作,两步操作不分先后> > 1. 配置URLconf> 2. 在应用/views.py中定义视图##### 项目准备 创建项目+创建应用+安装应用+配置模板路径+本地化+mysql数据库+URLconf+视图 * 安装应用 INSTALLED_APPS = 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'book.apps.BookConfig' mysql数据库使用之前的book DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 数据库主机 'PORT': 3306, # 数据库端口 'USER': 'root', # 数据库用户名 'PASSWORD': 'mysql', # 数据库用户密码 'NAME': 'book' # 数据库名字 } }
URLconf * settings.py中:指定url配置 ROOT_URLCONF = 'bookmanager01.urls' TEMPLATES = { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': \[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', , }, }, ] * 项目中urls.py:只要不是admin/就匹配成功,包含到应用中的urls.py from django.contrib import admin from django.urls import path,include urlpatterns = path('admin/', admin.site.urls), path('',include('book.urls')) * 应用中urls.py:匹配testproject/成功就调用views中的testproject函数,测试项目逻辑 from django.conf.urls import url import views urlpatterns = # 匹配`testproject/`成功就调用`views`中的`testproject`函数 url(r'\^testproject/KaTeX parse error: Expected 'EOF', got '#' at position 279: ... #̲ 测试项目逻辑 ...',index), # 匹配书籍列表信息的URL,调用对应的bookList视图 url(r'\^booklist/ ′ , b o o k L i s t , n a m e = ′ i n d e x ′ ) , u r l ( r ′ t e s t p r o j e c t / ',bookList,name='index'), url(r'\^testproject/ ′,bookList,name=′index′),url(r′testproject/',views.testproject,name='test'), ### 2 reverse反解析(通过名字找到路由)使用reverse函数,可以根据路由名称,返回具体的路径,如: from django.core.urlresolvers import reverse #或者 from django.urls import reverse def testproject(request): return HttpResponse("OK") # 定义视图:提供书籍列表信息 def bookList(request): url = reverse('book:test') print(url) return HttpResponse('index') > * 对于未指明namespace的,reverse(路由name)> * 对于指明namespace的,reverse(命名空间namespace:路由name)> >
> >
四、HttpRequest对象---------------利用HTTP协议向服务器传参有几种途径?> * 提取URL的特定部分,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取;> * 查询字符串(query string),形如key1=value1&key2=value2;> * 请求体(body)中发送的数据,比如表单数据、json、xml;> * 在http报文的头(header)中。### 1 URL路径参数> * 如果想从URL中获取值,需要在正则表达式中使用分组,> * 获取值分为两种方式> * 位置参数> * 参数的位置不能错> * 关键字参数> * 参数的位置可以变,跟关键字保持一致即可> * 注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式> * 分别使用以上两种获取URL值的方式提取出18 188> * http://127.0.0.1:8000/18/188/
位置参数(推荐使用) > * 应用中urls.py> > urlpatterns = \> path('booklist/',bookList),\> \> url(r'\^(d+)/(d+)/KaTeX parse error: Expected 'EOF', got '#' at position 535: ... \> #̲ 位置参数\> ...',detail),\> # 关键字参数\> url(r'\^(?Pd+)/(?Pd+)/KaTeX parse error: Expected 'EOF', got '#' at position 298: ...0d35edaeb5.png)#̲## 2 Django中的Qu...', views.register, name='register'), # 类视图:注册 url(r'\^register/KaTeX parse error: Expected 'EOF', got '#' at position 288: ...t), #̲ 位置参数 # ...',detail), # 关键字参数 url(r'\^(?Pd+)/(?Pd+)/KaTeX parse error: Expected 'EOF', got '#' at position 621: ...ponse('个人中心修改')#̲## 2、中间件Django中...',views.LoginView.as_view(),name='index'), #登录路由 url(r'\^transfer/KaTeX parse error: Expected 'EOF', got '#' at position 50: ...e='transfer'), #̲转账路由 ...',views.AdsView.as_view()), ] #定义视图 class AdsView(View): def get(self,request): return render(request,'index.html') * 前端代码实现
Title
我是网站B
> 运行测试,在用户登录网站A的情况下,点击网站B的按钮,可以实现伪造访问#### 在网站A中实现 csrf_token 校验的流程* 导入生成 csrf_token 的函数 from django.middleware.csrf import get_token csrf_token = get_token(request) * 在渲染转账页面的,做以下几件事情: 1. 生成 csrf_token 的值 2. 在返回转账页面的响应里面设置 csrf_token 到 cookie 中 3. 将 csrf_token 保存到表单的隐藏字段中 def get(self, request): # 生成csrf_token from django.middleware.csrf import get_token csrf_token = get_token(request) # 渲染转换页面,传入 csrf_token 到模板中 response = render(request, 'transfer.html',context={'csrf_token':csrf_token}) # 设置csrf_token到cookie中,用于提交校验 response.set_cookie('csrf_token', csrf_token) return response * 在转账模板表单中添加 csrf_token 隐藏字段
转账
我是网站A,转账页面
账户:
金额:
运行测试,进入到转账页面之后,查看 cookie 和 html 源代码
* 在执行转账逻辑之前进行 csrf_token 的校验 # 取出表单中的 csrf_token form_csrf_token = request.POST.get("csrftoken") # 取出 cookie 中的 csrf_token cookie_csrf_token = request.COOKIES.get('csrf_token') # 进行对比 if cookie_csrf_token != form_csrf_token: return HttpResponse('token校验失败,可能是非法操作') 运行测试,用户直接在网站 A 操作没有问题,再去网站B进行操作,发现转账不成功,因为网站 B 获取不到表单中的 csrf_token 的隐藏字段,而且浏览器有同源策略,网站B是获取不到网站A的 cookie 的,所以就解决了跨站请求伪造 的问题### 在 Django项目中解决 CSRF 攻击Django默认是开启CSRF的
模板中设置 CSRF 令牌 {% csrf_token %} 或者