Web 后端 开发
后端程序主要工作就是 数据管理。
通常 包括数据的 存储
(包括 增加、删除、修改)和 查询
。
这听起来似乎很简单,其实有的业务流程非常复杂 (想想淘宝购物),有时一个购买操作,要涉及到很多逻辑处理。
而且,如果设计用户量非常大,需要响应 百万级以上 的客户访问, 就需要精心的设计架构,做好多服务分布式、集群式的处理大量的用户请求。
通常,后端的开发涉及到:
-
静态文件服务方案
前端开发出来的
HTML
、css
、js
文件存储在什么地方,使用什么的服务提供给前端浏览器访问。通常一个比较大型的网站, 静态文件往往会使用单独的服务器专门提供服务。
一部分特别消耗带宽的数据(比如视频、图片)会使用第三方的云服务厂商(比如阿里云的
cdn
和oss
服务)。 -
API
接口设计, 就是 定义 前端和后端交互接口规范。目前流行的是
REST API
风格的接口,但是需要我们设计具体的API请求和响应消息的具体内容。这个通常应该是架构师设计的, 但是往往这工作经常会落到后端工程师头上。实际上 很多公司里面,系统架构师 也会做后端开发的工作。
-
数据库存储方案,比如:选择什么样的数据库,包括 关系型和非关系型的数据库。
-
数据库表结构设计, 要能合理、高效的存储业务数据,这样才能 高效查询、修改各种关联性的数据。
-
为了提高性能, 需要决定使用怎样的 缓存服务 和 异步任务服务
-
还有 其它种种特殊的考虑,比如 要熟悉目前日益流行的云存储技术,将有的数据,如图片,视频等 合理存储在云端
-
有的系统还需要有 大数据分析的需求 要后端高效实现。
一、Django相关介绍
1、什么是Django
web框架,指为解决一个开放性的问题而设计的具有一定约束性的架构。
一堆类库文件 有组织
是由python编写的,采用MTV模型。
Django官网:https://www.djangoproject.com/
框架的好处:
-
快速开发
-
简单易用
其他常见web框架:flask
web.py
Tornado
2、应用场景
快速搭建web应用 提供数据接口(API
)
CMDB
二、安装部署应用
准备工作:
1、安装python环境 python3以上
2、安装开发工具IDE Pycharm
1、安装Django
1.1、版本的选择
LTS:是长版本支持,一般我们选择都会选择LTS版本的,因为官方支持时间较长。
1.2、安装并创建项目
pip install django
跳转到目录 创建应用 目录根据实际情况选择
此处django-admin
要设置环境变量
找到django-admin.exe
的位置,加入系统环境变量
如系统中有多个python版本,选择默认python位置
C:\Users\Mocking\AppData\Local\Programs\Python\Python38\Scripts\
django-admin startproject mydjango
2、目录结构
manage.py django项目里面的工具,通过它可以调用django shell和数据库等。
settings.py
包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
urls.py
负责把URL模式映射到应用程序。
3、创建新应用
使用manage.py文件,创建应用。
python manage.py startapp app01
4、启动Django项目
python manage.py runserver
5、使用PyCharm打开项目
三、Django使用原理
1、MVT模型
- M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。
- V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
- T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。
2、请求流程
四、Django的请求和响应
1、快速实现
①定义路由 urls.py
②定义视图函数 views.py
③模型数据调用 创建表
④包含模板 加载模板 (html····)
1.1、路由定义
1.2、编写视图
1.3、浏览器访问
到这里,就完成了一个页面请求。
2、请求
https://docs.djangoproject.com/en/4.0/ref/request-response/
客户端请求服务器端携带的信息
属性:
HttpRequest.scheme
:请求的方式,即http
或者是https
HttpRequest.body
:请求的主体,返回的是一个字符串
HttpRequest.path
:请求的路径,这里的路径是指相对路径,也就是说一个登陆后台页面的请求:http://127.0.0.1:8000/admin 的路径是/admin
HttpRequest.method
:请求方式POST/GET
HttpRequest.encoding
:请求提交的数据的编码方式
HttpRequest.GET
:获取get
方式表单中或url
提交的数据
HttpRequest.POST
:获取post
方式表单中或url
提交的数据
HttpRequest.META
:获取的是一个标准的python
字典。它包含了所有的HTTP
请求信息方法:
HttpRequest.get_host()
:请求的地址
HttpRequest.get_port()
:请求的端口
HttpRequest.get_full_path()
:请求的完整路径,包括get
参数
下面是2个http请求消息的示例
GET /mgr/login.html HTTP/1.1
Host: www.sysmedia.com
User-Agent: Mozilla/6.0 (compatible; MSIE5.01; Windows NT)
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
POST /api/medicine HTTP/1.1
Host: www.sysmedia.com
User-Agent: Mozilla/6.0 (compatible; MSIE5.01; Windows NT)
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
name=qingmeisu&sn=099877883837&desc=qingmeisuyaopin
http请求消息由下面几个部分组成
请求行 request line
是http请求的第一行的内容,表示要操作什么资源,使用的 http协议版本是什么。
里面包含了3部分信息: 请求的方法,操作资源的地址, 协议的版本号
例如
GET /mgr/login.html HTTP/1.1
表示要 获取
资源, 资源的 地址
是 /mgr/login.html
, 使用的 协议
是 HTTP/1.1
而
POST /api/medicine HTTP/1.1
表示 添加
资源信息, 添加资源 到 地址 /api/medicine
, 使用的 协议
是 HTTP/1.1
GET、POST是请求的方法,表示这个动作的大体目的,是获取信息,还是提交信息,还是修改信息等等
常见的HTTP 请求方法包括:
-
GET
从服务器
获取
资源信息,这是一种最常见的请求。比如 要 从服务器 获取 网页资源、获取图片资源、获取用户信息数据等等。
-
POST,请求方法就应该是
添加
资源信息 到 服务器进行处理(例如提交表单或者上传文件)。比如 要 添加用户信息、上传图片数据 到服务器 等等
-
PUT
请求服务器
更新
资源信息 。比如 要 更新 用户姓名、地址 等等
-
DELETE
请求服务器
删除
资源信息 。比如 要 删除 某个用户、某个资源 等等
请求头 request headers
请求头是http请求行下面的 的内容,里面存放 一些 信息。
比如,请求发送的服务端域名是什么, 希望接收的响应消息使用什么语言,请求消息体的长度等等。
通常请求头 都有好多个,一个请求头 占据一行
单个请求头的 格式是: 名字: 值
HTTP协议规定了一些标准的请求头,点击查看MDN的描述
开发者,也可以在HTTP消息中 添加自己定义的请求头
消息体 message body
请求的url、请求头中 可以存放 一些数据信息, 但是 有些数据信息,往往需要 存放在消息体中。
特别是 POST、PUT等请求,添加、修改的数据信息 通常都是 存放在 请求消息体 中的。
如果 HTTP 请求 有 消息体, 协议规定 需要在 消息头和消息体 之间 插入一个空行, 隔开 它们。
请求消息体中保存了要提交给服务端的数据信息。
比如:客户端要上传一个文件给服务端,就可以通过HTTP请求发送文件数据给服务端。
文件的数据 就应该在请求的消息体中。
再比如:上面示例中 客户端要添加资源,资源的名称、编码、描述,就存放在请求消息体中。
WEB API 请求消息体 通常是某种格式的文本,常见的有
- Json
- Xml
- www-form-urlencoded
3、响应
服务器端返回给客户端的信息
属性:
HttpResponse.content
:响应内容
HttpResponse.status_code
:响应状态码
HttpResponse.content_type
:响应类型(默认是:text/html
)
下面是1个http响应消息的示例
HTTP/1.1 200 OK
Date: Thu, 19 Sep 2019 08:08:27 GMT
Server: WSGIServer/0.2 CPython/3.7.3
Content-Type: application/json
Content-Length: 37
X-Frame-Options: SAMEORIGIN
Vary: Cookie
{"ret": 0, "retlist": [], "total": 0}
HTTP响应消息包含如下几个部分
状态行 status line
状态行在第一行,包含3个部分:
-
协议版本
上面的示例中,就是
HTTP/1.1
-
状态码
上面的示例中,就是
200
-
描述状态的短语
上面的示例中,就是
OK
我们重点来看一下状态码,它表示了 服务端对客户端请求的处理结果 。
状态码用3位的数字来表示,第一位 的 数字代表 处理结果的 大体类型,常见的有如下几种:
• 2xx
通常 表示请求消息 没有问题,而且 服务器 也正确处理了
最常见的就是 200
• 3xx
这是重定向响应,常见的值是 301,302, 表示客户端的这个请求的url地址已经改变了, 需要 客户端 重新发起一个 请求 到另外的一个url。
• 4xx
表示客户端请求有错误, 常见的值有:
400 Bad Request
表示客户端请求不符合接口要求,比如格式完全错误
401 Unauthorized
表示客户端需要先认证才能发送次请求
403 Forbidden
表示客户端没有权限要求服务器处理这样的请求, 比如普通用户请求删除别人账号等
404 Not Found
表示客户端请求的url 不存在
• 5xx
表示服务端在处理请求中,发生了未知的错误。
通常是服务端的代码设计问题,或者是服务端子系统出了故障(比如数据库服务宕机了)
响应头 response headers
响应头 是 响应状态行下面的 的内容,里面存放 一些 信息。 作用 和 格式 与请求头类似,不再赘述。
消息体 message body
有时候,http响应需要消息体。
同样, 如果 HTTP 响应 有 消息体, 协议规定 需要在 消息头和消息体 之间 插入一个空行, 隔开 它们。
比如,白月SMS系统 请求 列出 药品 信息,那么 药品 信息 就在HTTP响应 消息体中
再 比如,浏览器地址栏 输入 登录网址,浏览器 请求一个登录网页的内容,网站服务器,就在响应的消息体中存放登录网页的html内容。
和请求消息体一样,WEB API 响应消息体 通常也是某种格式的文本,常见的有:
- Json
- Xml
- www-form-urlencoded
4、GET请求传参和接收
Get
请求是明文传输,信息附加在url
上面。
在HttpRequest
对象中,GET
属性是django.http.QueryDict
的实例,它是一个自定义的类似字典的类,用来处理同一个键带有多个值。这个类的需求来自某些HTML
表单元素传递多个值给同一个键。
request.GET
的QueryDict
在一个正常的请求/响应循环中是不可变的。
例:接收URL通过GET方式传输过来的参数,并打印到页面上
①接收到参数
②通过response返回参数
- 接收GET方式传值
- 传入多个参数,使用
&
隔开参数
http://127.0.0.1:8000/testget/?name=mocking&age=18
- 在
HttpResponse
获取get
- 多行获取加换行
def testget(request):
print(request.GET.get('name'))
data = request.GET
# return HttpResponse('测试访问get方法')
return HttpResponse("姓名:" + data.get('name') + "<br />年龄:" + data.get('age'))
5、POST请求传参和接收
POST
相对于Get
请求是安全的,所有信息附加在表单中。
在HttpRequest
对象中,POST属性是django.http.QueryDict
的实例,它是一个自定义的类似字典的类,用来处理同一个键带有多个值。这个类的需求来自某些HTML
表单元素传递多个值给同一个键。
request.POST
的QueryDict
在一个正常的请求/响应循环中是不可变的。
例:通过postman(接口调试工具)模拟发送POST请求,传输参数并把参数打印到页面
①postman发送数据
Tip:403 CSRF 禁止访问
解决方案一: 禁止关闭 CSRF 限制
https://docs.djangoproject.com/zh-hans/4.0/ref/csrf/
②返回数据信息
常见发送POST请求的方式:
①html表单
②ajax
③curl postman(开发API调试)
④编程语言里的一些操作方法和类 php curl libcurl python requests ulib
curl
方式请求Post
6、QueryDict对象
QueryDict常用操作方法:
QueryDict.get(key )
**QueryDict.getlist(key)**返回多个参数
QueryDict.items()
QueryDict.lists()
返回一个可迭代对象,取值时使用for循环遍历
返回值为元祖,lists返回类似字典格式
五、视图和模板
1、函数视图
以函数的方式定义的视图称为函数视图,函数视图便于理解。但是遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,但是代码可读性与复用性都不佳(后期会采用类视图)。
定义函数视图就跟定义一个函数是一模一样的,只是函数视图必须要接收一个参数request。
2、模板文件
①定义路由
②定义函数视图
现在已经可以看到输出文字,但是要求是显示返回一个静态页面。需要借助template支持。
静态网页文件下载地址:https://gitee.com/hellomocking/static-web-page-file
③建立templates文件夹和静态资源文件夹static
④把静态页面和静态资源放置到对应的目录
⑤在setting.py配置静态资源
⑥在函数视图中加载页面
render方法调用加载模板方法
render(request,模板名称)
⑦修改页面上的静态资源的访问地址
css js img 图片的路径 加上/static
六、路由
django的路由 可以进行自定义,具有丰富的用法。合理配置路由,对于web应用,具有易用的好处,还可以起到一定的安全作用。
1、URL匹配规则
①从上到下,依次匹配,如果匹配成功就不继续往下匹配了,
②如果匹配失败,继续匹配,直到匹配成功为止,
③如果没有匹配的对应规则,就会报错。
2、常见匹配方式
2.1、完全匹配
2.2、正则匹配
使用re_path()
代替path()
,并在字符串的引号前加r
。
Python正则表达式前的 r 表示原生字符串(rawstring),该字符串声明了引号中的内容表示该内容的原始含义,避免了多次转义造成的反斜杠困扰。大概意思就是加了
r`的不用再考虑字符串中标点的转义,程序会自动帮忙转义。
re_path(r'^testurl/(\d)/$', testurl)
2.3、分组匹配
分组正则匹配 (?p<标签名称>)
标签名称为之后接收的参数名称
re_path(r'^data/(?P<year>\d{4})/(?P<mouth>\d{2})/(?P<day>\d{2})', data)
3、反向解析URL
在前端页面中表单的提交地址,需要填写完整的URL地址,不利于使用和后期如有改动。
可以使用URL别名的方式来处理。
①定义前端页面地址
②路由URL定义别名
③模板上进行调用
查看解析效果
4、包含URL模块
在实际业务开发当中,会存在很多应用模块。如果把所有的url路由都定义到同一个文件,会很难进行维护,所有可以进行URL的分文件定义和管理。
①在app01下创建urls.py文件
②在urls.py中导入include,引入应用文件夹里的urls定义
③在对应的应用文件夹建立urls.py文件
④查看
案例:
- 主机列表模板部署
- 实现一个用户登录的原理
- 文件下载地址:https://gitee.com/hellomocking/static-web-page-file
步骤:
①定义路由
②编写函数视图加载模板
③编写模板页面
④处理参数,进行验证判断
文件导入如下:
实现页面:
七、类视图
1、类视图介绍
视图是一个可调用的对象,它接收一个请求然后返回一个响应,这个可调用对象可以不只是函数,Django还提供一些可以用作视图的类,叫做类视图。
以函数的形式进行定义的视图就是函数视图,视图函数便于理解,但是遇到一个视图函数对应的路径提供了多种不同的HTTP请求方式的支持时(get,post,delete,put),需要在一个函数中写不同的业务逻辑,代码的可读性和复用性就很低, 所以引入类视图进行解决。
2、使用类视图
①创建一个新的应用进行使用
- 设置APP分组路由
- 设置视图路由
②导入View类
③定义类视图,常见方法
④测试GET和POST方法
可以使用postman测试接口工具发送测试方法,或者使用CURL
curl 发送POST请求
3、简单登录逻辑实现
定义URL路由
定义类视图
编写模板
- 模板分应用部署
template
在多个app
项目中,若有重叠名称会重复访问,解决方式为在项目的template
下创建同名文件夹放模板文件
八、模板语法
1、变量的使用
在模板中,如果想要输出后端传输的变量。需要使用到模板的标签语法。
语法:
{{变量名称}}
例:在后端传入变量到模板中,在模板中调用输出变量
- 定义一个URL
- 定义一个模板
①在视图中传输变量
②在模板中调用输出变量
2、传递所有变量
当在视图需要往模板传输很多变量时,如果一个一个写,会很繁琐不方便,在框架中提供了,locals方法,可以传递所有变量。
在上面列子视图中,继续进行操作
①使用locals方法
②在模板中调用输出变量值
Tip:list和dict的值获取
获取list或者dict中的其中一个值,可以通过
.
进行获取。list填写数字下标,dict填写key。
3、过滤器
对于通过视图输出到模板中的数据,进行二次的处理。可以通过模板过滤器实现。
语法格式:
{{ obj | filter: param }}
常用的过滤器:
过滤器 | 作用 | 实例 |
---|---|---|
add | 给变量加上对应的值 | |
capfirst | 首字母大写 | |
cut | 从字符串中移除指定的字符 | |
date | 格式化日期字符串 | |
default | 如果值是False,就替换成设置的默认值,否则就用本来的值 |
例子:处理数字加
九、模板控制语句
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/
1、判断语句(if)
语法结构:
{% if %}{% endif %}
{% if %}...{%else%}...{% endif %}
{% if %}...{%elif%}...{%else%}...{% endif %}
if标签判断一个变量值,如果是ture,即为存在,不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}中间的所有内容。
提醒注意:通过请求接收到的数字,其实是一个字符串类型
2、循环语句(for)
语法结构:
{%for%}...{%endfor%}
{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}…{% endfor %}之间的所有内容。
2.1、遍历列表
模板标签写法
显示效果
倒序显示
计数器forloop.counter
forloop判断是否为第一个
2.2、遍历字典
十、自定义过滤器(扩展)
在上面列子中,学习使用了模板中提供的基本过滤器,但是有时候还是不能够满足业务需求。这时,可以选择使用自定义过滤器
自定义过滤器实现的步骤:
①在应用中创建
templatetags
②在其中创建任意
.py
结尾文件③导入
from django import template
方法④注册方法
register = template.Library()
⑤通过装饰器的写法,定制自定义过滤器
例:实现一个自定义过滤器
①创建模块templatetags
②创建一个.py结尾文件
③导入方法
④注册方法
⑤单个参数(使用装饰器register.filter)
my_tags.py
文件编写
模板调用
自定义标签在使用中,必须先加载
{% load my_tags %}
Tip:如果遇到以下问题,注意解决方案
⑥多参数(使用装饰器register.simple_tag)
十一、模板继承
在实际业务开发中,进行会使用页面中相同的部分,为了能够使页面模板部分可以复用。可以采用模板继承 的方式。
1、传统模板加载
①定义URL
②静态资源部署
③模板引入
注意:需要提前在setting.py中设置好模板路径和静态资源路径
④定义类视图
⑤修改引入静态资源的路径
css js
⑤查看页面加载效果
按照以上方式,继续快速创建一个用户管理的页面
使用传统模板加载方式的问题:
①公共部分
②修改了公共部分之后,需要修改多个页面
可以预见的是如果在多个页面中,都修改的话,工作量会很大,也不是很合适。
2、模板继承方式
解决思路:
①写基本页面base.html
base.html 是复制hostlist.html
②继承模板
创建一个新的newhostlist.html
注意在类视图中,调用的页面,应该是继承页面,不是基础页面
十二、ORM概念
1、ORM介绍
对象关系映射 用于实现面向对象编程语言里不同类型系统数据之间的转换。
其就是使用面向对象的方式,操作数据库进行表管理和增删改查操作等。
2、ORM的作用和优点
Django
中的对ORM进行封装,对接数据库引擎,执行对应的SQL语句。
使用者无需关心数据库引擎具体实现的软件(Mysql,sqlite…)。重点把握业务逻辑实现即可。之后如果数据库软件更换需要迁移,直接修改相关配置即可。
好处:
ORM使操作数据库变的更为简单、快捷。无需直接编写SQL语句,快速开发。
十三、ORM建表
1、映射关系
在Django框架中,通过ORM模型进行数据库的管理和操作。
通过Python代码,Django的ORM模型将代码转为SQL语句,操作数据库。
以下为对应关系:
类名 --> 表名
属性 --> 字段
类实例对象 --> 表记录
2、创建模型(表定义)
创建一个app03应用,模型代码的学习
①进入命令行
②执行创建新应用
创建一张表,只需在应用下的model.py中定义对应的类模型即可。继承models.Model。
常用的模型字段有哪些:
CharField -> 字符串类型
BooleanField -> 布尔类型
IntegerField -> 整数类型
DateField / DateTimeField -> 时间类型
EmailField -> Email类型
TextField -> 文本类型
更多类型参考:
https://docs.djangoproject.com/en/4.0/ref/models/fields/#django.db.models.CharField
例:编写一个类模型
3、字段属性
字段属性,用来限定字段的最大长度,Null值,默认值,主键,唯一性,备注等信息。
(1)max_length
CharField需要max_length参数来指定VARCHAR数据库字段的大小。
(2)null
如果为True,Django 将用NULL来在数据库中存储空值。 默认值是 False。
(3)default
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用。
(4)primary_key
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键,否则没必要设置任何一个字段的primary_key=True。
(5)unique
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的。
(6)verbose_name
备注的名字,可读更好。
(7)choices
由元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,而且这个选择框的选项就是choices 中的选项。
更多属性参考:https://docs.djangoproject.com/en/4.0/ref/models/fields/#field-types
根据提供的字段属性,设置合适的字段属性
sql
字段:
create table Host(
id 、、、、、,
hostname varchar(50) not null commint '主机名称',
.......
)
4、模型元数据(可选)
模型元数据是“任何不是字段的数据”,比如排序选项(ordering),数据库表名(db_table)。在模型中添加class Meta是完全可选的,所有选项都不是必须的。
Meta选项参数:
(1)db_table
指定自定义数据库表名的。Django有一套默认的按照一定规则生成数据模型对应的数据库表名,如果你想使用自定义的表名,就通过这个属性指定。
若不提供该参数, Django 会使用
app_label + '_' + module_name
作为表的名字。当你通过db_table
覆写表名称时,强烈推荐使用小写字母给表命名(2)ordering
这个字段是告诉Django模型对象返回的记录结果集是按照哪个字段排序的
例如:
class Meta: ordering = ['- name']
它是一个字符串的列表或元组。每个字符串是一个字段名,前面带有可选的“-”前缀表示倒序。前面没有
-
的字段表示正序。(3)verbose_name
可读性更高的名字。可以认为是一个表名注释。
更多的元数据设置参考:https://docs.djangoproject.com/en/4.0/ref/models/options/
5、迁移数据库(同步)
创建和迁移数据库表,一般执行两个步骤
①
makegrations
根据类模型 创建迁移文件②
migrate
通过迁移文件,进行数据表的创建和修改操作(连接数据库,管理表)
Tip:
当模型初次创建和修改都需要执行
①进入操作命令行
②执行makegrations命令,创建迁移文件
生成的migration迁移文件
③执行migrate迁移命令
以上操作就完成了Django中ORM模型。数据表的创建和修改已经完成。
问:Django连接数据库和数据表在哪里?表创建到哪儿了?
答:默认Django使用的sqlite数据库,sqlite是一个小型数据库,一个文件。
注:首次使用pycharm
的datebase
需要下载驱动才能显示数据
- 插入数据演示
插入完数据需要点击提交按钮进行提交!
6、更换数据库
在Django框架中,默认提供了sqllite数据库,进行开发和调试。
实际业务环境中,可以选择为业务数据库,比如说MySQL
6.1、windows安装mysql
https://dev.mysql.com/downloads/mysql/
https://dev.mysql.com/downloads/installer/
①获取软件包和下载器
②运行安装windows安装器
运行mysql-installer-community-5.7.37.0.msi
选择Server only
,我们主要目的不是对MySQL进行二次开发,而是基于MySQL提供的数据库服务,开发Web服务器,所以选择选择Server Only
。
- 安装完成
- 在管理员身份下执行命令初始化数据库
mysqld -install
mysqld --initialize --console
2022-04-19T14:38:30.421369Z 1 [Note] A temporary password is generated for root@localhost: lgM<IY8nb+uO
数据库初始化的root密码
默认解压目录没有data
文件夹
“mysqld --initialize --console”命令,可以得到mysql的初始密码,用mysqld --initialize 的目的是初始化data目录。要不然mysql5.7的解压文件夹下面不会出现data文件夹
- 接着就是在输入net start mysql启动服务
若出现如下报错
配置my.ini
配置文件
[mysql]
# 设置mysql客户端默认字符集
default-character-set=utf8
[mysqld]
# 设置3306端口
port=3306
character_set_server=utf8
# 解压目录
basedir=E:\mysql-5.7.37-winx64
# 解压目录下data目录
datadir=E:\mysql-5.7.37-winx64\data
default-storage-engine=INNODB
若仍显示报错:
1、使用mysqld --console
查看报错信息
2、找到ERROR
报错日志位置,显示端口被占用
3、mysqld --console
可以查看报错信息
netstat -ano
看看是端口是否被占用
netstat -aon|findstr “3306”
若被占用,PID结束进程,再试试看
成功启动:
- 开始使用mysql,输入命令:mysql -uroot -p,然后输入刚才的初始密码
- 修改密码
mysql> alter user 'root'@'localhost' identified by '123456';
mysql> flush privileges;
- 去除匿名用户
delete from mysql.user where user='';
- 使用
quit;
退出 - 输入命令:mysql -uroot -p,然后尝试新密码
③配合环境变量
添加MySQL的安装路径bin目录下
配置环境变量后的效果
④安装并启动MySQL服务
对于服务安装和卸载,都是需要使用cmd的管理员模式,否则没有权限
启动服务
改为手动启动
以上完成了windows下MySQL服务器的部署
6.2、Django配置使用MySQL
①修改settings.py配置
https://docs.djangoproject.com/en/4.0/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '', #你的数据库名称 数据库需要自己提前建好
'USER': '', #你的数据库用户名
'PASSWORD': '', #你的数据库密码
'HOST': '', #你的数据库主机,留空默认为localhost
'PORT': '3306', #你的数据库端口
'OPTIONS': {
"init_command": "SET sql_mode='STRICT_TRANS_TABLES'",
}
}
}
②使用MySQL创建数据库
MySQL的数据库需要提前创建,注意字符编码,统一为uf8
CREATE DATABASE 库名 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
③重新执行数据库迁移操作
cmd > pip install pymysql
或者:
- 导入
pymysql
包到__init__.py
中
再次执行迁移,查看数据库表
简单查看数据表及其结构
Tip:MySQL严格模式
出现问题
mysql 数据校验的严格模式,相关MySQL的配置解决,可以自定查询解决。
这里提供的是在Django里配置的方式。
解决方案
十四、ORM操作
https://docs.djangoproject.com/en/1.11/topics/db/queries/
1、添加数据
Django 使用一种直观的方式把数据库表中的数据表示成Python 对象:一个模型类代表数据库中的一个表,一个模型类的实例代表这个数据库表中的一条特定的记录。
使用关键字参数实例化模型实例来创建一个对象,然后调用save() 把它保存到数据库中。
也可以使用一条语句创建并保存一个对象,使用**create()**方法
定义url路由
在视图中导入模型类
(1)save
或者
(2)create
(3)create可以传入关键字参数kwargs
这里的**
表示一个字典
2、查询数据
(1)all方法
查询全部数据
Tip:模型类中定义返回的字段内容
(2)get方法
只取出一条数据,返回的是一个数据对象,如果查询的数据有多条或者没有都会抛出异常。
(3)filter方法
返回的是一个Queryset
,即使只查出一条数据,也是一个Queryset
。
查询的数据没有也是一个空的Queryset
,跟列表类似,列表的切片也可以使用。
(4)exclude方法
exclude
排除满足条件的,返回其他的
select * from hostlist where status != 1
(5)values方法
select * from hostlist
select hostname,ip from hostlist
values
方法提供了,查询需要显示的字段筛选。
如果需要显示多个字段,可以使用以下写法
3、更新数据
(1)操作对象的方式更新
我们先找到我们需要更新的数据,然后直接调用属性更改,最后save保存就可以了。
(2)使用update的方式修改数据(推荐)
4、删除数据
使用delete方法删除数据
5、ORM内置查询字段
使用__关键查询字段 双下划线
contains “模糊”大小写敏感的包含指定字符串
icontains “模糊”大小写不敏感的包含指定字符串
startswith, endswith 以指字字符串开头或结尾
in 在给定的列表内
gt 大于
gte 大于或等于
lt 小于
lte 小于或等于
range 在指定0`范围内
十五、ORM关联关系
运动会
一对一 一个运动员对应一个号码
多对一(一对多) 一个代表队可以被多个运动员申报
多对多 多个运动员可以报多个项目
1、多对一
多对一 就是一个对多个的关系。
比如:一本书只能对应一个出版社,而一个出版社可以出版多本书,这样就是多对一的关系。
多对一的关系,主要是通过主键和外键进行关联的。先有一再有多,先建立出版社,再出书。
在Django的ORM模型中,使用ForeignKey定义一对多的关系。
①创建模型一对多关系
django 升级到2.0之后,表与表之间关联的时候,必须要写
on_delete
参数,否则会报异常:
TypeError: init() missing 1 required positional argument: ‘on_delete’
on_delete各个参数的含义如下:
on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为
on_delete=models.CASCADE, # 删除关联数据,与之关联也删除
on_delete=models.DO_NOTHING, # 删除关联数据,什么也不做
on_delete=models.PROTECT, # 删除关联数据,引发错误ProtectedError
# models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
# models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)
on_delete=models.SET, # 删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
由于多对多(ManyToManyField)没有 on_delete 参数,所以以上只针对外键(ForeignKey)和一对一(OneToOneField)
DecimalFields
字段报错
查询官网:https://docs.djangoproject.com/zh-hans/4.0/ref/models/fields/
即: DecimalFields字段的“decimal_places”() 和 “max_digits” 属性必须被定义,不能忽略。
- 创建模型后,同步数据生成数据表
- 查看创建的数据表结构
②多对一关系操作
https://docs.djangoproject.com/en/4.0/topics/db/models/#relationships
添加数据 注意需要先添加一的关系,才能够添加多的关系。也就是此例中,先添加出版社,才可以添加图书。顺序和关联的先后,需要处理清楚。
- 先添加出版社信息
- 再添加图书信息
查询数据
- 通过书名称查询属于哪个出版社出版的 正向查询
- 通过出版社名称 查询出所有的该出版社出版的书籍 反向查询 对象实例
_set
sql
查询:
删除数据 删除出版社
当出版社删除后,对应的外键关系 图书也就跟着删除了 这是默认Django 多对一模型实现的
实际操作中:
如果在mysql中,图书属于某个出版社,这个出版社是不能够删除的
2、多对多
比如:一本书可以多个作者合作编写,一个作者也可以编写多本书,这样就是多对多的关系。
在Django的ORM模型中,使用ManyToManyField定义一对多的关系。
https://docs.djangoproject.com/en/4.0/topics/db/models/#many-to-many-relationships
操作方法
add(obj1, obj2, …) #添加一指定的模型对象到关联的对象集中。
create(**kwargs) #创建一个新的对象,将它保存并放在关联的对象集中。返回新创建的对象。
remove(obj1, obj2, …) #从关联的对象集中删除指定的模型对象。
clear() #从关联的对象集中删除所有的对象。
问题记录:
book
表字段名称写错
在models.py
中更改后,执行makemigrations
操作
之后执行migrate
报错
解决:可删除migration
记录文件,然后重新导入表结构。