django Web 开发简介 Python Django 网站开发培训 - 2周入门 web后端开发 web服务端开发 django 简介|菜鸟教程
1 、前后端分离的架构
后端只负责提供和处理响应数据
<1> 代码直接生成HTML
from django.http import HttpResponse
from common.models import Customer
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)
<2> 使用模板
使用Django的模板引擎
from django.http import HttpResponse
from common.models import Customer
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)
<3> 前后端分离架构
现在随着 浏览器中javascript 解释器性能的突飞猛进,以及一些前端模板库和框架的流行。很多架构师将 页面的html 内容生成 的任务放到前端。
这样 服务端就只负责提供数据, 界面的构成全部在前端(浏览器前端或者手机前端)进行,称之为前端渲染。
只是这个工作在前端执行, 使用前端的 框架库去完成,比如 Angular,React,Vue。
这样 界面完全交给前端开发人员去做, 后端开发只需要提供前端界面所需要的数据就行了。
前端 和 后端 之间的交互就完全是 业务数据了。 这样需要 定义好 前端和后端 交互数据 的接口。
目前通常这样的接口设计最普遍的就是使用 REST 风格的 API 接口。
前端通过 API 接口 从后端获取数据展示在界面上。 前端通过 API 接口 告诉后端需要更新的数据是什么。
通常 前后端的 API 接口 是由 架构师 设计的, 有时也可以由经验丰富的前端开发者、或者后端开发者设计。
接下来我们就聚焦在后端,我们的系统前端由另外的团队开发,我们只负责后端业务数据的维护
现在我们的系统,API接口 已经由架构师定义好了, 点击这里查看 API接口
我们只需要根据这个接口文档,实现后端系统的部分。 注意:需要Django返回的信息,通常都是所谓的 动态 数据信息。 比如:用户信息,药品信息,订单信息,等等。
这些信息通常都是存在数据库中,这些信息是会随着系统的使用发生变化的。
而 静态 信息,比如: 页面HTML文档、css文档、图片、视频等,是不应该由 Django 负责返回数据的。
这些数据通常都是由其他的 静态资源服务软件,比如 Nginx、Varnish等等,返回给前端。这些软件都会有效的对静态数据进行缓存,大大提高服务效率。在实际的项目中,往往还会直接使用 静态文件 云服务( OSS + CDN )提供静态数据的访问服务。
总之,Django处理并返回的应该是动态业务数据信息。
2、对资源的增查改删处理
数据的管理,主要就是:响应前端的请求, 对数据资源的 增加、修改、删除、列出 。
<1> 创建 mgr应用目录
接口文档明确说明了,这是针对 管理员用户 的 请求。
前面我们已经为 销售员用户 专门创建了一个应用 sales 来处理相关的 请求。
所以,我们可以 再为 管理员用户 专门创建一个应用 mgr 来处理相关的 请求。 怎么创建还记得吗?
对了,执行
python manage.py startapp mgr
<2> 添加处理请求模块 和 url 路由
【1】编写分发路由的函数
编写分发路由的函数, 来根据 http请求的类型 和请求体里面的参数 分发(或者说路由)给 不同的函数进行处理。
在 mgr/customer.py 中定义如下 dispatcher 函数
def dispatcher(request):
if request.method == 'GET':
request.params = request.GET
elif request.method in ['POST','PUT','DELETE']:
request.params = json.loads(request.body)
action = request.params['action']
if action == 'list_customer':
return listcustomers(request)
elif action == 'add_customer':
return addcustomer(request)
elif action == 'modify_customer':
return modifycustomer(request)
elif action == 'del_customer':
return deletecustomer(request)
else:
return JsonResponse({'ret': 1, 'msg': '不支持该类型http请求'})
【2】修改路由文件
接下来,根据 API 接口 ,我们发现 凡是 API 请求url为 /api/mgr/customers 的,都属于 客户 相关的API, 都应该交由 我们上面定义的dispatch函数进行分派处理。
那么我们需要在Django的url 路由文件中加入对应的路由。
所以, 第一步:我们应该在 总路由文件 config/urls.py 中定义了如下部分
path('api/mgr/', include('mgr.urls')),
第二步: 在 mgr 目录下面添加mgr/urls.py 路由文件, 并 加入如下声明即可, 如下所示
from django.urls import path
from mgr import customer
urlpatterns = [
path('customers', customer.dispatcher),
]
这样,就表示 凡是 API 请求url为/api/mgr/customers 的,都交由 我们上面定义的dispatch函数进行分派处理
<3> 对应接口文档编写函数操作客户数据
BYSMS系统 API 接口 1.0
【1】列出所有客户
请求消息
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"
}
]
}
函数 mgr/customer.py:
from common.models import Customer
def listcustomers(request):
qs = Customer.objects.values()
retlist = list(qs)
return JsonResponse({'ret': 0, 'retlist': retlist})
可以发现,无需转化数据为HTML, 后端的代码任务也大大减轻。
【2】 添加一个客户
mgr/customer.py:
def addcustomer(request):
info = request.params['data']
record = Customer.objects.create(name=info['name'] ,
phonenumber=info['phonenumber'] ,
address=info['address'])
【3】修改客户信息
根据接口文档,修改客户数据接口,前端提供的数据格式如下
{
"action":"modify_customer",
"id": 6,
"newdata":{
"name":"武汉市桥北医院",
"phonenumber":"13345678888",
"address":"武汉市桥北医院北路"
}
}
mgr/customer.py:
def modifycustomer(request):
customerid = request.params['id']
newdata = request.params['newdata']
try:
customer = Customer.objects.get(id=customerid)
except Customer.DoesNotExist:
return {
'ret': 1,
'msg': f'id 为`{customerid}`的客户不存在'
}
if 'name' in newdata:
customer.name = newdata['name']
if 'phonenumber' in newdata:
customer.phonenumber = newdata['phonenumber']
if 'address' in newdata:
customer.address = newdata['address']
customer.save()
return JsonResponse({'ret': 0})
【4】删除客户
根据接口文档,删除客户数据接口,前端只需要提供要删除的客户的ID。
数据格式如下
{
"action":"del_customer",
"id": 6
}
我们可以使用如下的函数来处理 mgr/customer.py:
def deletecustomer(request):
customerid = request.params['id']
try:
customer = Customer.objects.get(id=customerid)
except Customer.DoesNotExist:
return {
'ret': 1,
'msg': f'id 为`{customerid}`的客户不存在'
}
customer.delete()
return JsonResponse({'ret': 0})
【5】临时取消 CSRF 校验
根据接口文档,添加客户 请求是个Post请求
POST /网站名/api/mgr/signin HTTP/1.1
Content-Type: application/x-www-form-urlencoded
注意,缺省创建的项目, Django 会启用一个 CSRF (跨站请求伪造) 安全防护机制。
在这种情况下, 所有的Post、PUT 类型的 请求都必须在HTTP请求头中携带用于校验的数据。
为了简单起见,我们先临时取消掉CSRF的 校验机制,等以后有需要再打开。
要临时取消掉CSRF的 校验机制,非常简单,只需要在 项目的配置文件 config/settings.py 中 MIDDLEWARE 配置项 里 注释掉 django.middleware.csrf.CsrfViewMiddleware 即可。
<4> 与前端进行集成
最终终前端和后端系统会集成在一起成为一个完整的系统。
部署到生产环境(生产环境就是正式的线上运营环境)运行的架构往往比较复杂。
开发环境下, 前后端分离的架构如何简单集成。 前端环境其实就是 一些前端的代码和资源文件,包括 js文件、html文件、css文件 还有 图片视频文件等。
我们模拟前端团队开发的 前端 系统 打包在这里 ,点击这里下载
下载好以后,可以解压该 z_dist.zip 文件到项目根目录下面,形成一个目录 z_dist。
该目录下面就是前端的 代码资源文件。
Django的开发环境也可以从浏览器访问这些前端的资源文件。
但是前端文件都是静态文件,需要我们配置一下Django的配置文件, 指定http请求如果访问静态文件,Django在哪个目录下查找。
注意,接下来我们配置 Django 静态文件服务, 是 开发时 使用的 一种 临时方案 ,性能很低,这是方便我们调试程序用的。
开发模式: 前面讲过,正式部署web服务的时候,不应该这样干,应该采用其它方法,比如Nginx等。后面的教程会有详细的讲解如何使用Nginx 和 Django 组合使用。现在,请打开 config/urls.py 文件,在末尾 添加一个
from django.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('sales/', include('sales.urls')),
path('api/mgr/', include('mgr.urls')),
] + static("/", document_root="./z_dist")
在url 路由中加入 前端静态文件的查找路径。 访问http://localhost/mgr/index.html http://localhost/mgr/index.html#/
3、处理登录、登出请求
<1> 处理登录、登出请求
我们可以在mgr目录里面创建一个代码文件 sign_in_out.py ,用来处理管理员登录和登出 的API 请求的。
当我们执行 migrate 创建数据库表时,根据,就会为我们创建 用户表 auth_user ,如下所示
django.contrib.auth 这个app 已经 为我们做好了登录验证功能。 我们只需要使用这个app库里面的方法就可以了。 Django的文档就给出了登录和登出代码范例,我们稍微修改一下。
mgr/sign_in_out.py
from django.http import JsonResponse
from django.contrib.auth import authenticate, login, logout
def signin(request):
userName = request.POST.get('username')
passWord = request.POST.get('password')
user = authenticate(username=userName, password=passWord)
if user is not None:
if user.is_active:
if user.is_superuser:
login(request, user)
request.session['usertype'] = 'mgr'
return JsonResponse({'ret': 0})
else:
return JsonResponse({'ret': 1, 'msg': '请使用管理员账户登录'})
else:
return JsonResponse({'ret': 0, 'msg': '用户已经被禁用'})
else:
return JsonResponse({'ret': 1, 'msg': '用户名或者密码错误'})
def signout(request):
logout(request)
return JsonResponse({'ret': 0})
<2> 创建 url路由
系统中,浏览器登陆登录页面的url是 http://127.0.0.1/mgr/sign.html 但是这不是 登录 API接口的url路径。 根据接口,管理员登录的API 路径是 /api/mgr/signin 前面的课程, 我们已经在总路由文件config/urls.py 中 添加了如下路由记录
path('api/mgr/', include('mgr.urls')),
现在,我们只需要 在mgr 目录下面 的子路由文件 urls.py 里添加如下内容 mgr/urls.py
from mgr import customer
from django.urls import path
from mgr import sign_in_out
urlpatterns = [
path('customers', customer.dispatcher),
path('signin', sign_in_out.signin),
path('signout', sign_in_out.signout),
]
这样就表示:
如果有HTTP请求 url是/api/mgr/signin 就由 sign_in_out.py 里面的signin 函数处理,
如果有HTTP请求 url是/api/mgr/signout 就由 sign_in_out.py 里面的signout 函数处理。
<3>测试
【1】代码测试:
密码错误:
import pprint
import requests
payload = {
'username': 'admin',
'password': '88888888'
}
response = requests.post('http://localhost/api/mgr/signin',
data=payload)
pprint.pprint(response.json())
密码正确:
payload = {
'username': 'admin',
'password': '123456'
}
【2】界面测试:
成功直接跳转
|