好像文章变得越来越长了
于是决定每个主题单开一个文章
省的多图杀猫
接口 2018·10·21
其实后台和前台的对接对我来说一直是一个很玄学的东西
可能是因为缺乏基本全面的https知识
完全没办法理解前端是如何发送服务器后台可以理解的request并且服务器发回相应的前台可以理解的response的
以前印象中的前后端交互应该是这样的:
但是后来越想越不对劲
前后端完全不是一个环境
咋就这么开心的交换起数据来了
于是
好现在就卡在这个玄学里面了
那么为了解决这个问题
我用Django搭建的本地服务器做了个实验
基于此来探寻前端和后端交互的机制
(Django是啥?
好吧本布并不打算展开这个问题
不然今儿啥也别干了光写教程了
现在网上对于Django的小教程还是挺多的
大家可以自己学习一下
之后有空了可以补充上来)
实验准备
- 一个空的Django项目实例
- 一个空的小程序项目实例
为了纯粹测试网络前后端交互
咱们就弄的简单一点
不搞那么多功能了
Django端
首先来把Django这边搞定
我随便找了一个之前的练习项目搞起来了
省去前期的部署环节
(我才不会告诉你们其实是我忘记了怎么初始化项目)
算了
重新初始化一个吧
打开shell
认真严肃的找个文件夹
$ django-admin.py startproject server
然后run一下看看能不能出服务器
$ cd server
$ python3 manage.py runserver
本地服务器可以正常连接
很好
接下来创建个新的app来作为小程序后台
就叫miniapp就好了
$ python3 manage.py startapp miniapp
shell(就是Mac里的terminal)上的活儿到此
接下来用文档编辑器打开项目
我用的是Atom
反正看起来可以用就好了
我也没那么多要求
毕竟穷买不起Pycharm
TUT
数据库什么的暂时不需要就不整了
然后在miniapp目录下新建一个 urls.py
(我直接把主目录下面那个复制过去了)
修改一下主目录下的 urls.py
让它引用miniapp的 urls.py
(不知道为啥上面出现了链接效果
里面啥也没有
不要点)
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('miniapp/',include(('miniapp.urls','miniapp'), namespace = 'miniapp')),
]
这样如果待会儿输入127.0.0.1:8000/miniapp
后台会把我们指向miniapp
然后写一下我们miniapp里面urls.py的代码
from django.urls import path
from . import views
urlpatterns = [
path('answer', views.answer, name = 'answer'),
]
可以看到和主目录的urls.py比不太一样
那个admin就不说了
我们这里import 了一个views
这个指的是miniapp目录下的 views.py
我们待会儿会在views.py里面写我们的服务器后台响应函数
就是我们今天要测试的
服务器接收前台发来的request并发回给前台response
再看这个代码的第四行
我们定义了一个answer
也就是说这条url在浏览器里的地址是
127.0.0.1:8000/miniapp/answer
后面跟着views.answer
意思就是如果输入上面这个地址
服务器就会去运行咱们views.py里面的answer函数
(后面那个name就不用先管他了)
那么answer函数我们是不是还没写
现在写
服务器响应函数(后台)
好去到我们的server/miniapp/views.py
现在长这个样子:
空荡荡的是吧
我们需要先import http
紧接着第二行写
from django.http import HttpResponse
好下面我们就正式来写我们的响应函数了
其实我也不知道怎么写
那就先瞎写一个最简单的好了
我们之前在urls里面定义了引用函数的名字叫answer
所以接着下面在views里写:
def answer(request):
response = '卧槽居然成功了?!'
return HttpResponse(response)
假装上面这个代码如果可行的话
那么应该是
小程序只要给这个地址发个request
不管request里面包含什么参数
那么都能收到这条“卧槽居然成功了?!”
就这么简单?
嘿嘿
咱们试试看
小程序请求函数(前端)
我们假装服务器部署好了
小程序这边我们就弄个按钮
写个console返回程序就好了
在我们之前的hello world上写个按钮
长这样就行了
做实验就剩点事儿
我们绑定了一个点击函数ask
这个ask就是我们要实现的小程序向后台发送请求的功能
去home.js 里把这个绑定函数实现一下
Page({
data: {
// 留空以作备用
},
answer: function(){
wx.request({
url: '127.0.0.1:8000/miniapp/answer',
success(res){
console.log(res.data)
}
})
}
})
简单化嘛
直接就只发个request
啥也不干
实验开始
前后端都写好了
两边都保存
我们先照之前的步骤启动一下django的本地服务器
什么?居然运行不起来?!
不好意思
原来是刚才代码片段里的import少打了个p
一个p引发的血案
改完之后
服务器成功运行
然后来编译小程序
按下那个按钮
报错了
原来是小程序里的函数名字写错了
应该是ask而不是django里的answer
Page({
data: {
// 留空以作备用
},
ask: function(){
wx.request({
url: '127.0.0.1:8000/miniapp/answer',
success(res){
console.log(res.data)
}
})
}
})
改好了再编译
还是出错
难道是没有在地址前面加http?
真是矫情
改正一下再试
Page({
data: {
// 留空以作备用
},
ask: function(){
wx.request({
url: 'http://127.0.0.1:8000/miniapp/answer',
success(res){
console.log(res.data)
}
})
}
})
还是出错
不过看起来这回靠谱点了
点开文档查看发现
后台服务器的地址必须为域名而且要求备案
卧槽老子做个开发咋还这么多事儿
再去弄个备案这实验做哪辈子去
好在发现了一个设置
设置–》项目设置
钩上运行再试试
卧槽
??!
激动的跳了起来
先让我去开一杯八二年的老坛酸菜老干妈庆祝一下
- 5个小时以后
All right庆祝完了~
其实这段时间本布的进度又往后走了一下
目前实现了带参数的请求
发现写太多废话还挺耗费时间的…… 感觉这么写下去每天光写这个都要好久了
根据以上实验我们成功的建立了小程序和服务器的连接
说明服务器成功的收到了小程序的request
并且小程序也能收到服务器的response
并且从中解析出正确的String信息
我们可以总结出这一过程的模型:
这个过程能够实现的是:
- 小程序通过访问特定地址来拿到相应的信息
那么能实现的功能就比较有限:
- 只能像看报纸一样点哪里看哪里
- 登录啊搜索啊处理数据啊等等这些功能完全用不鸟
没错 完全就是一电子报纸
那么如果我们想发个参数给服务器
比如让它验证一下登录信息呢?
实验升级·带参数的请求
既然是带参数的request发出去
那我们可以做一个简单的参数处理实验:
小程序发一个用户名给服务器(暂定为admin)
服务器来判定用户名是否正确
如果正确就输出:登录成功
如果不正确就输出:用户名不正确
我们期待的模型应该是这样的:
那么先来写小程序端:
(参考了小程序的文档例子)
Page({
data: {
// 留空以作备用
},
ask2: function(){
wx.request({
url: 'http://127.0.0.1:8000/miniapp/answer2',
data:{
name:"admin"
},
success(res){
console.log(res.data)
}
})
})
为了长度我把ask函数删掉了
但是在我的程序里保留了
用一个新的ask2函数以和上一个实验区分开
url地址我们也要用answer2
这意味着django里要写一个新的函数来处理这个请求
根据小程序文档里的示例
我们把用户名变量name放在了data:{}里并把用户名设置为"admin"
感觉应该没什么问题吧?
当然,别忘了用一个新的按钮绑定ask2函数
<button bindtap='ask2'>模拟登录返回数据</button>
下面就是后台了:
我们需要增加一个对应的answer2函数在views.py里
以及相应的urls.py
from django.urls import path
from . import views
urlpatterns = [
path('answer', views.answer, name = 'answer'),
path('answer2',views.answer2, name = 'answer2'),
]
我们只需要加入第五行的新url即可
然后来写响应函数
views.py:
def answer2(request):
name = request.data.name
response = ''
if name == "admin":
response = '登录成功'
else:
response = '用户名不正确'
return HttpResponse(response)
回顾一下:
我们小程序里携带的参数name是写在data里面的
因此我们实验一下request.data.name是否是收到的参数所在
写完之后测试结果:
报错就算了
还列了好长一串
看来这么着行不通
去网上搜了一下request 后台解析
看了几篇文章之后发现一个问题:
小程序的request遵循https协议
https协议里面有多种方法
包含GET,POST
但是我们的小程序request里并没有定义这一点
查阅wx.request文档
发现:
似乎wx.request不写method就会自动套用GET函数
也就是说小程序这边的代码可能不用改
因为不需要再声明method为GET
那就只能改后台了
搜一下Django怎么解析GET request
在一大神博客上发现:
- request.GET
获取get方式表单中或url提交的数据
request.POST[“username”]
request.POST.get(“username”)
修改后台代码:
def answer2(request):
name = request.POST.get("name")
response = ''
if name == "admin":
response = '登录成功'
# return HttpResponse(response)
else:
response = '用户名不正确'
return HttpResponse(response)
居然返回了“用户名不正确”
说明方向是对了
但奇怪的是我们发的参数和后台是对应的
说明后台没有读取正确的参数
思考了一下
发现
既然request默认用GET方法
那么会不会是因为后台读取的是POST方法
因此读空了?
改成GET试一下:
def answer2(request):
name = request.GET.get("name")
response = ''
if name == "admin":
response = '登录成功'
# return HttpResponse(response)
else:
response = '用户名不正确'
return HttpResponse(response)
“登录成功“!!!!
??!!
不能高兴太早
我们再反向实验一下
这次把用户名故意改成错的
修改小程序:
ask2: function(){
wx.request({
url: 'http://127.0.0.1:8000/miniapp/answer2',
data:{
name:"admin1"
},
success(res){
console.log(res.data)
}
})
我们把admin改成了admin1
与后台对照不符
运行结果:
??!!!
实验成功
说明后台成功处理了request用GET方式传递的参数
并返回了响应的数据
我们也可以更新一下小程序和服务器交互的模型:
掌握到这里
基本上可以实现相当一部分前后端交互功能了
另外根据我在搜request方法时看的文章
GET只能携带少量参数
如果我们需要提交大型数据
比如表单
就必须使用POST来实现
明天我们来研究怎么搞POST
晚安各位
22 Oct 2018 00:27 am