Django+微信小程序开发待办清单:通讯和登录
3464 views, 2022/01/25 updated Go to Comments
开发 Web 版 Todo-List,首先需要解决两个问题:
- 建立小程序和 Django 之间的通讯,这是一切工作的基础。
- 建立用户登录机制,以区分后端中数据的归属。
本章就来解决通讯问题,并分步骤搞定登录问题。
Django接口
学过 Django 的同学都知道,Django 项目是以 App 的形式组织起来的。所以第一步就是万年不变的创建 App 了。
在 backend 路径开启命令行,输入下面的神秘文字:
(venv) backend> python manage.py startapp weixin
创建了个叫 weixin
的 App。
现在你的后端目录结构应该是这样的:
backend/ -- manage.py -- backend/ -- ... -- weixin/ -- migrations/ -- __init__.py -- admin.py -- apps.py -- models.py -- tests.py -- views.py
如果你读过我以前的系列文章 Django搭建个人博客 或者 Django-Vue 搭建个人博客,应该就对 App 中生成的这些文件相当熟悉了。
接下来在 weixin/views.py
中随便写个视图,以便测试功能:
# weixin/views.py from rest_framework.views import APIView from rest_framework.response import Response class WeixinLogin(APIView): def get(self, request, format=None): """ 提供 get 请求 """ return Response({"data": "hello world."})
视图类 WeixinLogin()
基于 DRF 框架 APIView
,它通过实现 get()
函数,提供了一个简单的 GET 请求。
然后创建 weixin/urls.py
文件,配置子路由:
# weixin/urls.py from django.urls import path from weixin.views import WeixinLogin app_name = 'weixin' urlpatterns = [ path('login/', WeixinLogin.as_view(), name='login'), ]
接着修改 backend/urls.py
给子路由分配上级路由:
# backend/urls.py from django.contrib import admin from django.urls import path, include urlpatterns = [ ... # 增加了这行 path('api/weixin/', include('weixin.urls', namespace='weixin')), ]
最后注册 App:
# backend/settings.py ... INSTALLED_APPS = [ ... 'weixin', ]
运行 runserver 服务器,在浏览器中输入地址 http://127.0.0.1:8000/api/weixin/login/
:
“hello world.”
小程序请求
后台能够正常返回数据了,但是还需要在小程序中获取数据。
首先准备工作。小程序为了安全起见,默认 web 请求必须具有 HTTPS 证书。本地的 runserver 显然没有此证书,因此得打开小程序开发工具右上侧的“详情”配置,勾选”不校验合法域名、web-view、TLS版本以及HTTPS证书“:
接下来写代码,向 Django 后端发送请求。还记得前面说过的小程序通用接口 wx.[xxx]
吗?它又来了,这次的作用是发请求。
修改小程序项目 pages/index/index.js
的生命周期函数,添加 wx.request()
相关代码:
// pages/index/index.js Component({ // ... lifetimes: { attached() { // ... wx.request({ url: 'http://127.0.0.1:8000/api/weixin/login/', success(res) { console.log(res.data) } }) }, }, })
保存文件并刷新模拟器,加载完页面后,调试器中就将取得的数据打印出来了:
注意,勾选的”不校验HTTPS证书“选项仅在开发时有效。后续真正部署到线上时,记得老老实实将域名升级为 HTTPS 。
通讯算是搞定了,下面将进入本教程最核心的部分:用户登录。
登录流程图
将数据存到云端,首要问题就是要解决身份认证问题,也就是俗话说的用户登录了。
Django 和小程序的登录比较麻烦的是,用户的身份是由微信提供的(因为是微信用户嘛),所以需要小程序客户端、微信接口服务、Django后端的三方交互,并且要保证敏感数据的安全性。
看下面这个非常重要的微信官方提供的流程图:
看不懂没关系,我帮你总结下:
- 小程序通过微信接口获取临时登录凭证Code。
- 小程序将Code发送到Django服务器。
- Django服务器将Code发送到微信接口服务,换取openid等身份凭证。
- Django服务器将身份凭证与自身的用户建立对应关系,并返回小程序token。
- 小程序通过token请求业务数据。
接下来将分几章,逐步实现上图中的登录及业务流程。
后端获取凭证
任何第三方(比如我们的 Django 服务器)必须要提供小程序的 AppID 和 AppSecret ,才能从微信通用接口请求对应的数据。这很好理解,如果任何不经认证的第三方都能获取到用户的信息,那也太危险了。所以 AppID 和 AppSecret 是很重要的信息,只能在后台查看。
在前面的章节中,读者应该已经注册了小程序测试号了。再次从微信公众平台登录测试号:
然后就能在后台查看你的 AppID 和 AppSecret 了:
将它们记录好,接下来会用到。
然后在小程序开发工具中,确保你的账号是登录状态。后续的功能都是基于模拟器中的微信用户身份。
再看一眼开头的流程图。第一步是小程序需要向开发者服务器(即 Django 服务器)发送临时登录凭证Code。
修改前端中 js 文件的 attached()
函数,使小程序启动时自动发送 Code :
// frontend/pages/index/index.js // ...其他代码省略 // 修改 attached() lifetimes: { attached() { wx.login({ success(res) { if (res.code) { //发起网络请求 wx.request({ // 这里是django的本地ip地址 // 如果部署到线上,需要改为接口的实际网址 url: 'http://127.0.0.1:8000/api/weixin/login/', // 请求方式修改为 POST method: 'POST', data: { code: res.code } }) } else { console.log('登录失败!' + res.errMsg) } } }) }, },
前端暂时这样就 ok 了,接下来开发后端 Django 代码。
还是根据流程图,Django 收到 Code 后,需要拿着 Code 和微信接口服务通信。因此先在虚拟环境中安装网络请求库 requests
:
(venv) > pip install requests
完成后,修改上一章的视图类 WeixinLogin()
,使其具有真正实用的功能:
# backend/weixin/views.py from rest_framework.views import APIView from rest_framework.response import Response import requests import json class WeixinLogin(APIView): def post(self, request, format=None): """ 提供 post 请求 """ # 从请求中获得code code = json.loads(request.body).get('code') # 填写你的测试号密钥 appid = 'wxa0...42d4' appsecret = '7077...4a48' # 微信接口服务地址 base_url = 'https://api.weixin.qq.com/sns/jscode2session' # 微信接口服务的带参数的地址 url = base_url + "?appid=" + appid + "&secret=" + appsecret + "&js_code=" + code + "&grant_type=authorization_code" response = requests.get(url) # 处理获取的 openid try: openid = response.json()['openid'] session_key = response.json()['session_key'] except KeyError: return Response({'code': 'fail'}) else: # 打印到后端命令行 print(openid, session_key) return Response({'code': 'success'})
它做了两件事情:
- 将 Code 发送到微信接口服务,换取到 openid 等关键身份信息。
- 将 openid 打印到 Django 命令行中。
注意视图类现在仅接受 POST 请求了。
获取到的 openid 和 session_key 打印出来大概是这个样子:
ow5rb5.........nJbgj-hT9w 9B3Rmx.......7Yxs2/GA==
接下来的章节中我们将只用到 openid。当用户使用了微信小程序,后台会产生一个唯一的openid,可以通过这个来区分不同的用户。
会话密钥 session_key 是对用户数据进行了加密签名的密钥。注意:为了应用自身的数据安全,开发者不应该把会话密钥下发到小程序,也不应该对外提供这个密钥。
自定义登录态
拿到 openid 后,就相当于拿到当前用户的身份证号,接下来需要将 openid 和 Django 服务器自身的数据库中的用户对应起来。
修改视图类如下:
# backend/weixin/views.py ... from django.contrib.auth.models import User class WeixinLogin(APIView): def post(self, request, format=None): """ 提供 post 请求 """ ... # 处理获取的 openid try: ... except KeyError: ... else: # 根据openid确定用户的本地身份 try: user = User.objects.get(username=openid) except User.DoesNotExist: user = None if user: user = User.objects.get(username=openid) else: user = User.objects.create( username=openid, password=openid ) return Response({'code': 'success'})
- 如果存在用户名为 openid 的用户,则将其取出。
- 如果不存在,则新建用户名为 openid 的用户,并取出。
这里对数据库进行了多次查询,你可以尝试优化一下。
这样就可以了!试试多次重启小程序,Django后端将随之自动在数据库中创建或搜索对应的本地用户。
你可以在 Django 后台中确认。创建超级用户:
(venv) > python manage.py createsuperuser
浏览器访问 http://127.0.0.1:8000/admin/
登录后台,查看 User
:
下面那个就是通过 openid 创建的用户了。
总结
对比开头那个流程图,我们已经把用户登录上半部分给搞好了。
接下来的章节整用户登录下半部分,继续走起。