1. 说明
使用前后端分离的模式。
前端:微信小程序(以下简称“小程序”)
后端:Django REST framework
2. 前端部分
2.1 wxss
使用微信原生样式WeUI。使用方法详见这里。
2.2 wxml
2.2.1 <form>组件
当点击 form 表单中 form-type 为 submit 的 button 组件时,会将表单组件中的 value 值进行提交,需要在表单组件中加上 name 来作为 key。
使用radio时,name应当加在radio-group里
2.2.2 <button>组件
就是按钮。
2.2.3 示例代码
wxml
<form bindsubmit="formSubmit">
<view class="weui-form__opr-area"> <!--此处class表示使用了相应的weui样式-->
<button formType="submit" type="primary">确定</button>
</view>
</form>
JavaScript
Page({
formSubmit: function (e) {
console.log('form发生了submit事件,携带数据为:', e.detail.value)
},
})
2.3 js
2.3.1 wx.request() API
小程序提供了wx.request() API用于发起https请求
- 需要在method属性中填入GET或POST等等以发起相应请求
- 数据格式默认为json,会自动对数据进行 JSON 序列化,可改
- 不包含文件
官方示例代码
wx.request({
url: 'test.php', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success (res) {
console.log(res.data)
}
})
2.3.2 wx.uploadFile() API
小程序还提供了wx.uploadFile() API用于将本地资源上传到服务器
- 会发起一个https POST请求
- 每次都必须且仅能上传一个文件
- 可在上传文件的同时携带表单数据
官方示例代码
wx.uploadFile({
url: 'https://example.weixin.qq.com/upload', //仅为示例,非真实的接口地址
filePath: tempFilePaths[0],
name: 'file',
formData: {
'user': 'test'
},
success (res){
const data = res.data
//do something
}
})
2.3.3 示例代码
使用wx.request()时无法上传文件,而使用wx.uploadFile()时必须包含一个文件,但实际表单里用户可以选择添加或不添加图片。于是,需要判断是否有图片,并分别调用相应的方法。
结合上述wxml部分提交表单相应代码,最终js代码如下:
pageName.js
Page({
/**
* 页面的初始数据
*/
data: {
files: [],
},
/* “确定”按钮被点击 */
formSubmit: function (e) {
console.log('form发生了submit事件,携带数据为:', e.detail.value);
var formData = e.detail.value; //提取表单数据
if (this.canSubmit(formData)) //判断是否满足提交条件,比如用户输入的数据是否有误
{
/*向服务器发送数据,有图和无图时调用的方法不同*/
if (this.data.files[0]) {
/*若有图*/
wx.uploadFile({
url: 'http://127.0.0.1:8000/app/api/', //服务器API
filePath: this.data.files[0],
name: 'image',
formData: formData, //表单数据
})
}
else {
/*若无图*/
wx.request({
url: 'http://127.0.0.1:8000/app/api/', //服务器API
data: formData, //表单数据
method: 'POST',
})
}
}
else {
console.log('不能提交')
}
},
})
2.4 补充说明
在小程序中使用网络相关的 API 时,有诸多问题需要注意。
在开发时可做如下设置:
3. 后端部分
本人实际操作前学习了孙振强的《Django REST framework 初体验》,获益匪浅。
3.1 新建应用
python manage.py startapp appName
把新应用移动到项目根目录的apps
文件夹下。如果没有的话,就新建一个。当应用多了之后,放在一个文件夹里会有便于管理。
3.2 注册应用
每当新建了应用之后,不要忘了在settings.py
里注册新应用。
settings.py
INSTALLED_APPS = [
...
'rest_framework',
'apps.appName'
]
3.3 编写模型
apps\appName\model.py
from django.db import models
class ClassName(models.Model):
image = models.ImageField(upload_to="images/%Y/%m/", null=True, blank=True)
upload_to里填的是后端接收到文件之后的保存路径,上传文件之后会自动创建。
%Y表示年份,%m表示月份,便于分类管理。
注意:使用ImageField需要先安装Pillow
pip install Pillow
3.4 配置数据库
每当新建或修改了model.py
之后,不要忘了做数据迁移。
python manage.py makemigratons appName
python manage.py migrate appName
如果不想用django自带的数据库,可在settings.py
中修改。
3.5 修改设置
在settings.py
里添加以下内容,设置静态文件路径为项目根目录下的media文件夹。
settings.py
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
3.6 编写序列化模块
在apps\appName\
下新建文件serializers.py
apps\appName\serializers.py
from rest_framework import serializers
from .models import ClassName
class ClassNameSerializer(serializers.ModelSerializer):
class Meta:
model = ClassName
fields = '__all__' # 默认生成所有字段
3.7 编写视图
apps\appName\views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import ClassName
from .serializers import ClassNameSerializer
class ClassNameView(APIView):
def get(self, request, format=None):
class_name = ClassName.objects.all()
serializer = ClassNameSerializer(class_name, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = ClassNameSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3.8 编写路由
3.8.1 应用路由
apps\appName\urls.py(没有的话就新建一个)
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^api/$', views.ClassNameView.as_view())
]
3.8.2 项目路由
项目根目录\urls.py(这个不可能没有)
from django.contrib import admin
from django.urls import path
from django.conf import settings
from django.conf.urls import url, include
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
url(r'^api-auth/', include('rest_framework.urls')),
url(r'^app/', include('apps.appName.urls'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
4. 参考文献
本文所有参考文献均已以链接的形式标注在了对应位置。