参考B站up主:https://www.bilibili.com/video/BV1AE41117Up?
一、Django的安装与运行
1.安装
- Django 框架是用Python语言开发的, 所以安装Django 就像安装其他的 Python库一样,执行如下命令即可
C:\Users\fanb>pip install django
C:\Users\fanb>python -m django --version
3.2.5
2.创建项目
C:\Users\fanb>e:
E:\>cd python
E:\python>django-admin startproject fanb_django
最外层 fanb_django 就是项目根目录 e:\python\fanb_django\ , 项目文件都放在里面。
manage.py 是一个工具脚本,用作项目管理的。以后我们会使用它执行管理操作。
里面的 fanb_python 目录是python包。 里面包含项目的重要配置文件。这个目录名字不能随便改,因为manage.py 要用到它
fanb_django\settings.py 是 Django 项目的配置文件. 包含了非常重要的配置项,以后我们可能需要修改里面的配置。
fanb_django\urls.py 里面存放了 一张表, 声明了前端发过来的各种http请求,分别由哪些函数处理.
fanb_django\wsgi.py python组织制定了 web 服务网关接口(Web Server Gateway Interface)规范 ,简称wsgi。参考文档 https://www.python.org/dev/peps/pep-3333/
3.运行 Django web服务
E:\python>cd fanb_django
E:\python\fanb_django>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
July 18, 2021 - 16:38:02
Django version 3.2.5, using settings 'fanb_django.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
打开浏览器,地址栏输入 ‘http://127.0.0.1:8000/’ ,就可以看到如下的界面,表示Django服务搭建成功,启动成功。
注意,启动web服务的命令行窗口不能关闭,如果关闭,web服务就停止了。
CTRL+C也可以停止。
二、HTTP请求的url路由
1.创建项目app(application)
这里以 实现一个公司的“销售管理系统发”为案例。
管理员管理的功能 做在一个名字为 mgr的app里面
销售人员的操作 实现在另外一个名字为 sales的app里面
- 进入项目根目录,通过以下命令,创建sales的app。
E:\python\fanb_django>python manage.py startapp sales
刚才我们创建的 sales 应用里面 有个 views.py 文件。 这个文件里面通常是写处理http 请求的代码的。
打开 views.py , 在里面加入如下内容
from django.http import HttpResponse
def listorders(request):
return HttpResponse("下面是系统中所有的订单信息。。。")
这里面最终的返回结果是 HttpResponse 对象的参数字符串 ,也就是这句话
"下面是系统中所有的订单信息。。。’’
listorders的参数 request 是Django中的 HttpRequest 对象,包含了HTTP请求中的信息。
后端程序处理请求,常常要根据请求中的数据进行相应的处理
光是定义了这样一个函数不行的,我们需要 告诉 Django :
当前端发送过来的HTTP请求 url地址 是 /sales/orders/ , 就由 views.py 里面的函数 listorders 来处理
2.url路由
这个文件是 url路由设置的入口文件。
打开该文件,在 urlpatterns 列表变量中添加一条路由信息,结果如下
from django.contrib import admin
from django.urls import path
from sales.views import listorders
urlpatterns = [
path('admin/', admin.site.urls),
path('sales/orders/',listorders)
]
urlpatterns 列表 就是 Django 的 url 路由的入口,里面是一条条的路由记录。
就是告诉 当前端过来的请求 url地址 是 /sales/orders/ , 就由 views.py 里面的函数 listorders 来处理。
所以,所谓 路由 就是指 : 根据 HTTP请求的url路径, 设置 由哪个 函数来处理这个请求。
3.路由子表
url 路由表就是可以像上面这样,一个请求对应一个处理函数。
但是有的时候,我们的项目比较大的时候, 请求的url 会特别多。
这时,我们通常可以将不同的路由记录 按照功能 分拆到不同的 url路由子表 文件中。
比如,这里我们可以把 访问 的 url 凡是 以 sales 开头的全部都 由 sales app目录下面的 子路由文件 urls.py 处理。
- 首先在 sales 目录下面创建一个新的文件
sales\urls.py 。然后在这个 sales\urls.py 文件中输入如下内容
from django.urls import path
from sales.views import listorders,listorders1,listorders2
urlpatterns = [
path('orders/', views.listorders),
path('orders1/', views.listorders1),
path('orders2/', views.listorders2),
]
- 然后,再修改主url路由文件
fanb_django/urls.py , 如下
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('sales/',include('sales.urls'))
]
- 在
fanb_django/views.py 中添加listorder1和listorders2函数
from django.http import HttpResponse
def listorders(request):
return HttpResponse("下面是系统中所有的订单信息。。。")
def listorders1(request):
return HttpResponse("下面是系统中所有的订单信息1。。。")
def listorders2(request):
return HttpResponse("下面是系统中所有的订单信息2。。。")
三、数据库
1.创建数据库
关系型数据库系统,常用的开源数据库有 mysql 和 postgresql。
但是上面这些数据库,都需要我们安装数据库服务系统 和 客户端库,比较麻烦,现在先使用另一种更简单的 数据库 sqlite。
E:\python\fanb_django>python manage.py migrate
就会在 项目的根目录下面 生成一个配置文件中指定的数据库文件 db.sqlite3 。
- 通过 https://sqlitestudio.pl/index.rvt?act=download 下载sqlite 数据库工具 sqlitestudio
下载后解压即可, 运行该工具, 然后打开上面的 文件 db.sqlite3
2.ORM的概念
通常,在Django中,定义一张数据库的表就是定义一个继承自 django.db.models.Model 的类
定义该表中的字段(列), 就是定义该类里面的一些属性
类的方法就是对该表中数据的处理方法,包括 数据的增删改查
这种通过 对象 操作数据库 的方法 被称之为 ORM (object relational mapping)
首先再创建一个名为common的应用目录,里面存放一些项目所需要的公共的表的定义。
E:\python\fanb_django>python manage.py startapp common
打开 common/models.py,加入如下内容
from django.db import models
class Customer(models.Model):
name = models.CharField(max_length=200)
phonenumber = models.CharField(max_length=200)
address = models.CharField(max_length=200)
在项目的配置文件 settings.py 中, INSTALLED_APPS 配置项 加入如下内容
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'common.apps.CommonConfig',
]
在项目根目录下执行命令
E:\python\fanb_django>python manage.py makemigrations common
Migrations for 'common':
common\migrations\0001_initial.py
- Create model Customer
发现在 common\migrations 目录下面出现了0001_initial.py, 这个脚本就是相应要进行的数据库操作代码。
随即,执行如下命令,真正去数据库创建表
E:\python\fanb_django>python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, common, contenttypes, sessions
Running migrations:
Applying common.0001_initial... OK
- 用 sqlitestudio 查看数据库,发现创建了一张名为 common_customer的表
注意
如果以后我们修改了models.py 里面的库表的定义,都需要再次运行 python manage.py makemigrations common 和 python manage.py migrate 命令,使数据库同步该修改结果
3.Django Admin 管理数据
Django提供了一个管理员操作界面可以方便的 添加、修改、删除你定义的 model 表数据。
执行如下命令,依次输入要创建的管理员的 登录名、email、密码
E:\python\fanb_django>python manage.py createsuperuser
Username (leave blank to use 'fanb'): fanb
Email address: 1916861581@qq.com
Password:
Password (again):
Superuser created successfully.
密码至少八个字符
- 修改应用里面的 管理员 配置文件 common/admin.py,注册定义的model类
from django.contrib import admin
from .models import Customer
admin.site.register(Customer)
- 访问127.0.0.1:8000/admin,登录刚刚创建的账号
点击定义的customers表
点击下面的 ADD CUSTOMER 按钮来添加一条客户记录
在跳出的界面中输入客户信息后,点击SAVE按钮
使用数据库查看工具,就发现数据库中确实有了添加的数据信息
- 如果你是中文的操作系统,想使用中文的admin界面,应该在配置文件
settings.py 中 MIDDLEWARE 最后加入如下配置
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',
'django.middleware.locale.LocaleMiddleware',
]
要注意上面的界面 Django 内置的给管理员使用的。只是实现了一些通用的功能,而且界面语言偏英语的。
在实际的工作项目中, 还是需要我们自己开发前端界面给他们使用。
4.读取数据库表记录
- 在文件sales/views.py 中,定义一个listcustomers 函数
from django.http import HttpResponse
from common.models import Customer
def listorders(request):
return HttpResponse("下面是系统中所有的订单信息。。。")
def listcustomers(request):
qs = Customer.objects.values()
retStr = ''
for customer in qs:
for name, value in customer.items():
retStr += f'{name} : {value} | '
retStr += '<br>'
return HttpResponse(retStr)
Customer.objects.values() 就会返回一个 QuerySet 对象,这个对象是Django 定义的,在这里它包含所有的Customer 表记录。
- 修改路由表, 加上对
sales/customers/ url请求的 路由
在sales/urls.py 修改
from django.urls import path
from sales.views import listorders,listcustomers
urlpatterns = [
path('orders/', listorders),
path('customers/',listcustomers)
]
- 通过
127.0.0.1:8000/sales/customers/ 查看
5.过滤条件
- 通过
filter 方法加入过滤条件,修改view里面的代码
from django.http import HttpResponse
from common.models import Customer
def listorders(request):
return HttpResponse("下面是系统中所有的订单信息。。。")
def listcustomers(request):
qs = Customer.objects.values()
ph = request.GET.get('phonenumber', None)
if ph:
qs = qs.filter(phonenumber=ph)
retStr = ''
for customer in qs:
for name, value in customer.items():
retStr += f'{name} : {value} | '
retStr += '<br>'
return HttpResponse(retStr)
filter的过滤条件可以有多个,只要继续在后面的参数添加过滤条件即可。比如
qs = qs.filter(phonenumber=ph,address='山东菏泽曹县')
- 通过
127.0.0.1:8000/sales/customers/?phonenumber=1314159 查看
四、前后端分离架构
1.代码直接生成HTML
HTML本身其实也是字符串,只是这个字符串里面的内容是符合HTML语言规范的。
既然它也是字符串,我们可以使用Python直接构建出 HTML 字符串内容。
html_template ='''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
table {
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
</style>
</head>
<body>
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>电话号码</th>
<th>地址</th>
</tr>
%s
</table>
</body>
</html>
'''
def listcustomers(request):
qs = Customer.objects.values()
ph = request.GET.get('phonenumber',None)
if ph:
qs = qs.filter(phonenumber=ph)
tableContent = ''
for customer in qs:
tableContent += '<tr>'
for name,value in customer.items():
tableContent += f'<td>{value}</td>'
tableContent += '</tr>'
return HttpResponse(html_template%tableContent)
用一个变量 html_template 存储html模板, 然后 代码中生成html 里面需要插入的表格记录的内容,这个内容是html片段,也就是 html 表格的每行 。最后填入到 html_template 模板里面,就产生了完整的HTML 字符串。
访问 127.0.0.1:8000/sales/customers/ 查看
2.使用模板
上面使用python直接拼接出HTML内容,但是当HTML中有多处内容需要插入时,就会很繁杂,不好维护。
很多后端框架都提供了一种 模板技术, 可以在html 中嵌入编程语言代码片段, 用模板引擎(就是一个专门处理HTML模板的库)来动态的生成HTML代码
修改一下代码,使用Django的模板引擎
html_template ='''
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
table {
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
</style>
</head>
<body>
<table>
<tr>
<th>id</th>
<th>姓名</th>
<th>电话号码</th>
<th>地址</th>
</tr>
{% for customer in customers %}
<tr>
{% for name, value in customer.items %}
<td>{{ value }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
</body>
</html>
'''
from django.template import engines
django_engine = engines['django']
template = django_engine.from_string(html_template)
def listcustomers(request):
qs = Customer.objects.values()
ph = request.GET.get('phonenumber',None)
if ph:
qs = qs.filter(phonenumber=ph)
rendered = template.render({'customers':qs})
return HttpResponse(rendered)
直接把要生成的 HTML片段 写在 HTML模板 里面。
然后,只需要传入渲染模板所需要的参数就可以了,模板引擎会自动化帮我们生成的HTML
访问浏览器,得到一样的结果。
3.前后端分离架构
-
现在随着 浏览器中javascript 解释器性能的突飞猛进,以及一些前端模板库和框架的流行。很多架构师将 页面的html 内容生成 的任务放到前端。这样 服务端就只负责提供数据, 界面的构成全部在前端(浏览器前端或者手机前端)进行,称之为前端渲染。 -
需要 定义好 前端和后端 交互数据 的接口。目前通常这样的接口设计最普遍的就是使用 REST 风格的 API 接口。 -
前端通过 API 接口 从后端获取数据展示在界面上。前端通过 API 接口 告诉后端需要更新的数据是什么。通常 前后端的 API 接口 是由 架构师 设计的, 有时也可以由经验丰富的前端开发者、或者后端开发者设计。 -
接下来我们就聚焦在后端,我们的系统前端由另外的团队开发,我们只负责后端业务数据的维护。
五、API接口
1.概述
本接口用于 fanb_django 系统 管理员用户 前后端系统 之间的数据 交互。
本接口中,所有请求 ( 除了登录请求之外 ),必须在cookie中携带有登录的成功后,服务端返回的sessionid。
本接口中,所有请求、响应的消息体 均采用 UTF8 编码
2.登录系统
POST /api/mgr/signin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
http 请求消息 body 中 参数以 格式 x-www-form-urlencoded 存储
需要携带如下参数,
username 用户名
password 密码
HTTP/1.1 200 OK
Content-Type: application/json
http 响应消息 body 中, 数据以json格式存储,
如果登录成功,返回如下
{
"ret": 0
}
如果登录失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "用户名或者密码错误"
}
3.客户数据
请求消息
GET /api/mgr/customers?action=list_customer HTTP/1.1
请求参数
http 请求消息 url 中 需要携带如下参数,
action
填写值为 list_customer
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果获取信息成功,返回如下
{
"ret": 0,
"retlist": [
{
"address": "江苏省常州武进市白云街44号",
"id": 1,
"name": "武进市 袁腾飞",
"phonenumber": "13886666666"
},
{
"address": "北京海淀区",
"id": 4,
"name": "北京海淀区代理 蔡国庆",
"phonenumber": "13990123456"
}
]
}
ret 为 0 表示登录成功
retlist 里面包含了所有的客户信息列表。
请求消息
POST /api/mgr/customers HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带添加客户的信息
消息体的格式是json,如下示例:
{
"action":"add_customer",
"data":{
"name":"武汉市桥西医院",
"phonenumber":"13345679934",
"address":"武汉市桥西医院北路"
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果添加成功,返回如下
{
"ret": 0,
"id" : 677
}
如果添加失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "客户名已经存在"
}
请求消息
PUT /api/mgr/customers HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带修改客户的信息
消息体的格式是json,如下示例:
{
"action":"modify_customer",
"id": 6,
"newdata":{
"name":"武汉市桥北医院",
"phonenumber":"13345678888",
"address":"武汉市桥北医院北路"
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果修改成功,返回如下
{
"ret": 0
}
如果修改失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "客户名已经存在"
}
请求消息
DELETE /api/mgr/customers HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带要删除客户的id
消息体的格式是json,如下示例:
{
"action":"del_customer",
"id": 6
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果删除成功,返回如下
{
"ret": 0
}
如果删除失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "id为 566 的客户不存在"
}
4.药品
请求消息
GET /api/mgr/medicines HTTP/1.1
请求参数
http 请求消息 url 中 需要携带如下参数,
action
填写值为 list_medicine
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果获取信息成功,返回如下
{
"ret": 0,
"retlist": [
{"id": 1, "name": "青霉素", "sn": "234324234234", "desc": "青霉素"},
{"id": 2, "name": "红霉素", "sn": "234545534234", "desc": "红霉素"}
]
}
每个药品信息以如下格式存储
{"id": 2, "name": "红霉素", "sn": "234545534234", "desc": "红霉素"}
请求消息
POST /api/mgr/medicines HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带添加药品的信息
消息体的格式是json,如下示例:
{
"action":"add_medicine",
"data":{
"desc": "青霉素 国字号",
"name": "青霉素",
"sn": "099877883837"
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果添加成功,返回如下
{
"ret": 0,
"id" : 677
}
如果添加失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "药品名已经存在"
}
请求消息
PUT /api/mgr/medicines HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带修改药品的信息
消息体的格式是json,如下示例:
{
"action":"modify_medicine",
"id": 6,
"newdata":{
"name":"武汉市桥北医院",
"phonenumber":"13345678888",
"address":"武汉市桥北医院北路"
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果修改成功,返回如下
{
"ret": 0
}
如果修改失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "药品名已经存在"
}
请求信息
DELETE /api/mgr/medicines HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带要删除药品的id
消息体的格式是json,如下示例:
{
"action":"del_medicine",
"id": 6
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果删除成功,返回如下
{
"ret": 0
}
如果删除失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "id为 566 的药品不存在"
}
5.订单
请求消息
GET /api/mgr/orders HTTP/1.1
请求参数
http 请求消息 url 中 需要携带如下参数,
action
填写值为 list_order
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果获取信息成功,返回如下
{
"ret": 0,
"retlist": [
{id: 1, name: "华山医院订单001", create_date: "2018-12-26T14:10:15.419Z", customer_name: "华山医院",medicines_name: "青霉素"},
{id: 2, name: "华山医院订单002", create_date: "2018-12-27T14:10:37.208Z", customer_name: "华山医院",medicines_name: "青霉素 | 红霉素 "}
]
}
每个订单信息以如下格式存储
{
id: 2,
name: "华山医院订单002",
create_date: "2018-12-27T14:10:37.208Z",
customer_name: "华山医院",
medicines_name: "青霉素 | 红霉素 "
}
其中 medicines_name 表示对应的药品,如果该订单有多个药品, 中间用 竖线隔开
请求消息
POST /api/mgr/orders HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带添加订单的信息
消息体的格式是json,如下示例:
{
"action":"add_order",
"data":{
"name":"华山医院订单002",
"customerid":3,
"medicineids":[1,2]
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果添加成功,返回如下
{
"ret": 0,
"id" : 677
}
如果添加失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "订单名已经存在"
}
请求消息
DELETE /api/mgr/orders HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带要删除订单的id
消息体的格式是json,如下示例:
{
"action":"delete_order",
"id": 6
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果删除成功,返回如下
{
"ret": 0
}
如果删除失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "id为 566 的订单不存在"
}
{
id: 2,
name: "华山医院订单002",
create_date: "2018-12-27T14:10:37.208Z",
customer_name: "华山医院",
medicines_name: "青霉素 | 红霉素 "
}
其中 medicines_name 表示对应的药品,如果该订单有多个药品, 中间用 竖线隔开
请求消息
POST /api/mgr/orders HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带添加订单的信息
消息体的格式是json,如下示例:
{
"action":"add_order",
"data":{
"name":"华山医院订单002",
"customerid":3,
"medicineids":[1,2]
}
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果添加成功,返回如下
{
"ret": 0,
"id" : 677
}
如果添加失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "订单名已经存在"
}
请求消息
DELETE /api/mgr/orders HTTP/1.1
Content-Type: application/json
请求参数
http 请求消息 body 携带要删除订单的id
消息体的格式是json,如下示例:
{
"action":"delete_order",
"id": 6
}
响应消息
HTTP/1.1 200 OK
Content-Type: application/json
响应内容
http 响应消息 body 中, 数据以json格式存储,
如果删除成功,返回如下
{
"ret": 0
}
如果删除失败,返回失败的原因,示例如下
{
"ret": 1,
"msg": "id为 566 的订单不存在"
}
|