【微信小程序+Django REST framework】无图或单图表单提交

1. 说明

使用前后端分离的模式。
前端:微信小程序(以下简称“小程序”)
后端:Django REST framework

2. 前端部分

2.1 wxss

使用微信原生样式WeUI。使用方法详见这里

2.2 wxml

2.2.1 <form>组件

将组件内的用户输入的switch input checkbox slider radio picker 提交。

当点击 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 时,有诸多问题需要注意
在开发时可做如下设置:

详情 - 本地设置 - 不校验合法域名.png

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. 参考文献

本文所有参考文献均已以链接的形式标注在了对应位置。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350