Django之开发微信小程序后端-Django篇②

3-1 Request&Response对象

在这里插入图片描述
在这里插入图片描述

3-2 Django的RESTful URL设计

在这里插入图片描述

3-3 实现个人助手功能清单发布

apis\views\menu.py 管理app
在app.js中定义全局接口地址
在这里插入图片描述
定义传递的应用数据

// pages/menu/menu.js

const app = getApp()

Page({

  /**
   * 页面的初始数据
   */
  data: {
    grids: [{
      "name": "应用1"
    }, {
      "name": "应用2"
    }], // 九宫格内容
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.updateMenuData()
  },

  /**
   * 请求后台,更新menu数据
   */
  updateMenuData: function() {
    var that = this
    wx.request({
      url: app.globalData.serverUrl + app.globalData.apiVersion + '/service/menu',
      success: function(res) {
        var menuData = res.data.data
        console.log(menuData)
        that.setData({
          grids: menuData
        })
      }
    })
  },

页面渲染数据
在这里插入图片描述

3-4 实现图文消息

这里是采用本地存储
在这里插入图片描述

在这里插入图片描述

3-5 Django类视图

import json
from django.views import View
from django.http import HttpResponse, JsonResponse

from utils.response import CommonResponseMixin
from thirdparty import juhe


class WeatherView(View, CommonResponseMixin):
    def get(self, request):
        pass

    def post(self, request):

        data = []
        received_body = request.body.decode('utf-8')
        received_body = json.loads(received_body)
        print(received_body)
        cities = received_body.get('cities')
        for city in cities:
            result = juhe.weather(city.get('city'))
            result['city_info'] = city
            data.append(result)
        response_data = self.wrap_json_response(data)
        return JsonResponse(data=response_data, safe=False)
class CommonResponseMixin(object):
    @classmethod
    def wrap_json_response(cls, data=None, code=None, message=None):
        response = {}
        if not code:
            code = ReturnCode.SUCCESS
        if not message:
            message = ReturnCode.message(code)
        if data is not None:
            response['data'] = data
        response['result_code'] = code
        response['message'] = message
        return response

3-6 Django图文消息应用

#!/usr/bin/python                                                                  

import os
import hashlib
from django.views import View
from django.http import Http404, HttpResponse, FileResponse, JsonResponse
from backend import settings
from utils.response import ReturnCode, CommonResponseMixin


class ImageListView(View, CommonResponseMixin):
    def get(self, request):
        image_files = os.listdir(settings.IMAGES_DIR)
        response_data = []
        for image_file in image_files:
            response_data.append({
                'name': image_file,
                'md5': image_file[:-4]
            })
        response = self.wrap_json_response(data=response_data)
        return JsonResponse(data=response, safe=False)


class ImageView(View, CommonResponseMixin):
    def get(self, request):
        md5 = request.GET.get('md5')
        imgfile = os.path.join(settings.IMAGES_DIR, md5 + '.jpg')
        print(imgfile)
        if os.path.exists(imgfile):
            data = open(imgfile, 'rb').read()
            # return HttpResponse(data, content_type='image/jpg')
            return FileResponse(open(imgfile, 'rb'), content_type='image/jpg')
        else:
            response = self.wrap_json_response(code=ReturnCode.RESOURCE_NOT_FOUND)
            return JsonResponse(data=response, safe=False)

    def post(self, request):
        files = request.FILES
        response_data = []
        for key, uploaded_file in files.items():
            print(key)
            print(uploaded_file)
            content = uploaded_file.read()
            md5 = hashlib.md5(content).hexdigest()
            path = os.path.join(settings.IMAGES_DIR, md5 + '.jpg')
            print(md5)
            with open(path, 'wb+') as f:
                f.write(content)
            response_data.append({
                'name': key,
                'md5': md5
            })
        response = self.wrap_json_response(data=response_data, code=ReturnCode.SUCCESS)
        return JsonResponse(data=response, safe=False)

    def delete(self, request):
        md5 = request.GET.get('md5')
        img_name = md5 + '.jpg'
        path = os.path.join(settings.IMAGES_DIR, img_name)
        if os.path.exists(path):
            os.remove(path)
            message = 'remove success.'
        else:
            message = 'file(%s) not found.' % img_name
        response = self.wrap_json_response(code=ReturnCode.SUCCESS, message=message)
        return JsonResponse(data=response, safe=False)

3-8 综合实践之生活服务-上

在这里插入图片描述
pages/weather.js

// pages/weather/weather.js

const app = getApp()

const popularCities = [
  // {
  //   "province": "上海市",
  //   "city": "上海",
  //   "area": "徐汇区"
  // },
  {
    "province": "河南省",
    "city": "郑州",
    "area": "回族区"
  }
]

Page({

  /**
   * 页面的初始数据
   */
  data: {
    isAuthorized: false,
    weatherData: null
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.updateWeatherData()
  },

  updateWeatherData: function() {
    wx.showLoading({
      title: '加载中',
    })
    var that = this;
    wx.request({
      url: app.globalData.serverUrl + app.globalData.apiVersion + '/service/weather',
      method: 'POST',
      header: {
        'content-type': 'application/json' // 默认值
      },
      // 查询的城市
      data: {
        cities: popularCities
      },
      success: function(res){
        console.log(res.data.data)
        that.setData({
          weatherData: res.data.data
        })
        wx.hideLoading()
      }
    })
  },


  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {
    this.updateWeatherData()
  }
})

Django后端在上面
在这里插入图片描述

3-8 综合实践之生活服务-下

在这里插入图片描述
主要上图片备份,小程序前端back.js逻辑

const app = getApp()
const imageUrl = app.globalData.serverUrl + app.globalData.apiVersion + '/service/image'

Page({
  data: {
    // 需要上传的图片
    needUploadFiles: [],
    // backupedFiles每个元素四个字段 name, md5, path, isDownloaded
    // 已下载的备份图片
    downloadedBackupedFiles: []
  },

  // 选择图片上传
  chooseImage: function(e) {
    var that = this;
    wx.chooseImage({
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function(res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        that.setData({
          needUploadFiles: that.data.needUploadFiles.concat(res.tempFilePaths)
        });
      }
    })
  },

  // 长按确认函数
  longTapConfirm: function(e) {
    var that = this
    // 上传视图的确认菜单
    var uploadConfirmList = ['取消上传']
    // 已备份图片列表视图的确认菜单
    var downloadedConfirmList = ['保存本地', '删除备份']
    if (e.currentTarget.dataset.type == 'UploadView') {
      var itemList = uploadConfirmList
    } else {
      var itemList = downloadedConfirmList
    }
    // 显示菜单
    wx.showActionSheet({
      itemList: itemList,
      success: function(res) {
        if (res.cancel) {
          return
        }
        // 上传视图的确认菜单逻辑
        if (e.currentTarget.dataset.type == 'UploadView' && res.tapIndex == 0){
          var imgId = e.currentTarget.dataset.id
          var newNeedUploadFiles = that.data.needUploadFiles
          for (var i = 0; i < newNeedUploadFiles.length; i ++){

            if(newNeedUploadFiles[i] == imgId){
              newNeedUploadFiles.splice(i, 1)
            }
            that.setData({
              needUploadFiles: newNeedUploadFiles
            })
          }
        }
        // 已备份图片列表视图的确认菜单逻辑
        if (e.currentTarget.dataset.type == 'DownloadedView' && res.tapIndex == 1){
          var imgIndex = e.currentTarget.dataset.index
          var imgItem = that.data.downloadedBackupedFiles[imgIndex]
          console.log(imgIndex)
          console.log(imgItem)
          console.log(that.data.downloadedBackupedFiles)
          var newDownloadedBackupedFiles = that.data.downloadedBackupedFiles
          newDownloadedBackupedFiles.splice(imgIndex, 1)
          console.log(newDownloadedBackupedFiles)
          that.setData({
            // 删除图片本地
            downloadedBackupedFiles: newDownloadedBackupedFiles
          })
          // 删除图片远端
          that.deleteBackup(imgItem)
        }
      }
    });
  },

  // 上传图片文件
  uploadFiles: function() {
    var that = this
    that.setData({
      newBackupedFiles: []
    })
    for (var i = 0; i < this.data.needUploadFiles.length; i++) {
      var file = this.data.needUploadFiles[i]
      wx.uploadFile({
        url: app.globalData.serverUrl + app.globalData.apiVersion + '/service/image',
        filePath: file,
        name: 'test',
        success: function(res) {
          var resutData = JSON.parse(res.data)
          var imgData = resutData.data[0]
          var uploadedFile = {
            'name': imgData.name,
            'md5': imgData.md5,
            'path': '',
            'isDownloaded': false
          }
          // 上传成功的保存到newBackupedFiles数组里
          that.downloadFile(uploadedFile)
        }
      })
    }
    wx.showToast({
      title: '上传成功',
    })
    // 清空等待上传的文件列表
    this.setData({
      needUploadFiles: []
    })
  },


  // 删除图片
  deleteBackup: function(imgItem){
    console.log('delete a backup file.' + imgItem)
    wx.request({
      url: imageUrl + '?md5=' + imgItem.md5,
      method: 'DELETE',
      success: function(res){
        console.log(res)
        wx.showToast({
          title: '删除成功',
        })
      }
    })
  },

  onLoad: function(){
    this.downloadAllFromRemote()
  },

  // 下载所有的已备份图片
  downloadAllFromRemote: function () {
    var that = this
    // 1. 请求后台获取已备份的图片列表
    wx.request({
      url: imageUrl + '/list',
      method: 'GET',
      success: function (res) {
        var imageList = res.data.data
        for (var i = 0; i < imageList.length; i++) {
          // 2. 逐个调用downloadFile进行图片下载
          that.downloadFile(imageList[i])
        }
      }
    })
  },

  // 下载图片
  downloadFile: function (imgItem) {
    var that = this
    var downloadUrl = imageUrl + '?md5=' + imgItem.md5
    wx.downloadFile({
      url: downloadUrl,
      success: function (res) {
        var filepath = res.tempFilePath
        console.log(filepath)
        var newDownloadedBackupedFiles = that.data.downloadedBackupedFiles
        imgItem.path = filepath
        newDownloadedBackupedFiles.unshift(imgItem)
        that.setData({
          downloadedBackupedFiles: newDownloadedBackupedFiles
        })
        console.log(newDownloadedBackupedFiles)
      }
    })
  },
});

3-9 小程序股票、星座等功能实现

在这里插入图片描述

实现技术

实现技术:后端主要是利用聚合数据api接口,来查询出相应APP应用API所获取的数据返回给小程序前端,具体的示例也可参考上面获取 天气的例子

def stock(market, code):
    '''
    沪深股票
    :param market: 上交所 = sh, 深交所 = sz
    :param code: 股票编号
    :return:
    '''
    key = ''
    api = 'http://web.juhe.cn:8080/finance/stock/hs'
    params = 'gid=%s&key=%s' % (market + code, key)
    url = api + '?' + params
    print(url)
    response = requests.get(url=url, proxies=proxy.proxy())
    data = json.loads(response.text)
    data = data.get('result')[0].get('data')
    response = {
        'name': data.get('name'),
        'now_price': data.get('nowPri'),
        'today_min': data.get('todayMin'),
        'today_max': data.get('todayMax'),
        'start_price': data.get('todayStartPri'),
        'date': data.get('date'),
        'time': data.get('time')
    }
    response['is_rising'] = data.get('nowPri') > data.get('todayStartPri')
    sub = abs(float(data.get('nowPri')) - float(data.get('todayStartPri')))  # 差值
    response['sub'] = float('%.3f' % sub)
    return response
"""
stock api
{
	'resultcode': '200',
	'reason': 'SUCCESSED!',
	'result': [{
		'data': {
			'buyFive': '123700',
			'buyFivePri': '33.780',
			'buyFour': '41262',
			'buyFourPri': '33.790',
			'buyOne': '11747',
			'buyOnePri': '33.820',
			'buyThree': '134600',
			'buyThreePri': '33.800',
			'buyTwo': '92600',
			'buyTwoPri': '33.810',
			'competitivePri': '33.820',
			'date': '2020-05-29',
			'gid': 'sh600036',
			'increPer': '-1.17',
			'increase': '-0.400',
			'name': '招商银行',
			'nowPri': '33.820',
			'reservePri': '33.850',
			'sellFive': '13100',
			'sellFivePri': '33.890',
			'sellFour': '95400',
			'sellFourPri': '33.880',
			'sellOne': '1500',
			'sellOnePri': '33.850',
			'sellThree': '1000',
			'sellThreePri': '33.870',
			'sellTwo': '1200',
			'sellTwoPri': '33.860',
			'time': '15:00:00',
			'todayMax': '34.130',
			'todayMin': '33.700',
			'todayStartPri': '33.860',
			'traAmount': '1260905545.000',
			'traNumber': '372374',
			'yestodEndPri': '34.220'
		},
		'dapandata': {
			'dot': '33.820',
			'name': '招商银行',
			'nowPic': '-0.400',
			'rate': '-1.17',
			'traAmount': '126091',
			'traNumber': '372374'
		},
		'gopicture': {
			'minurl': 'http://image.sinajs.cn/newchart/min/n/sh600036.gif',
			'dayurl': 'http://image.sinajs.cn/newchart/daily/n/sh600036.gif',
			'weekurl': 'http://image.sinajs.cn/newchart/weekly/n/sh600036.gif',
			'monthurl': 'http://image.sinajs.cn/newchart/monthly/n/sh600036.gif'
		}
	}],
	'error_code': 0
}

获取小程序应用名字

在app.yml中定义小程序的名字,注册路由返回给小程序前端

published:
  - app:
      category: life
      application: weather
      name: 天气
      publish_date: 2018-10-01
      url: /service/weather
      desc: this is a weather app.
  - app:
      category: life
      application: backup-image
      name: 图片备份
      publish_date: 2018-10-02
      url: /service/image
      desc: this is a backup image app.
  - app:
      category: life
      application: stock
      name: 股票
      publish_date: 2018-10-03
      url: /service/stock
      desc: this is a stock app.

  - app:
      category: life
      application: constellation
      name: 星座运势
      publish_date: 2018-10-03
      url: /service/constellation
      desc: this is a constellation app.

  - app:
      category: life
      application: joke
      name: 笑话
      publish_date: 2018-10-03
      url: /service/joke
      desc: this is a joke app.

apis\views\menu.py

import os
import yaml

from django.http import JsonResponse

from backend import settings

import utils.response


def init_app_data():
    data_file = os.path.join(settings.BASE_DIR, 'app.yaml')
    with open(data_file, 'r', encoding='utf-8') as f:
        apps = yaml.load(f)
        return apps

def get_menu(request):
    global_app_data = init_app_data()
    published_apps = global_app_data['published']
    # return JsonResponse(data=published_apps, safe=False, status=200)
    response = utils.response.wrap_json_response(data=published_apps)
    return JsonResponse(data=response, safe=False)

在这里插入图片描述

总结

backup是定义后端逻辑,如上传图等

server是定义各个app获取接口数据,传递给前端等操作,前端共用一个页面,通过判断应用类型来显示api的数据

小程序中menu是定义app应用页面,如获取后端传递的app名称,跳转app页面等操作
在这里插入图片描述

  • 在前段app.json中定义整体的配置

    {
      "pages": [
        "pages/index/index",
        "pages/menu/menu",
        "pages/backup/backup",
        "pages/weather/weather",
        "pages/stock/stock",
        "pages/service/service"
      ],
      "window": {
        "backgroundTextStyle": "light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle": "black"
      },
      "tabBar": {
        "list": [
          {
            "pagePath": "pages/index/index",
            "text": "首页",
            "iconPath": "",
            "selectedIconPath": ""
          },
          {
            "pagePath": "pages/menu/menu",
            "text": "应用",
            "iconPath": "",
            "selectedIconPath": ""
          }
        ]
      },
      "sitemapLocation": "sitemap.json"
    }
    
// pages/menu/menu.js

const app = getApp()

Page({

  /**
   * 页面的初始数据
   */
  data: {
    grids: [{
      "name": "应用1"
    }, {
      "name": "应用2"
    }], // 九宫格内容
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.updateMenuData()
  },

  /**
   * 请求后台,更新menu数据
   */
  updateMenuData: function() {
    var that = this
    wx.request({
      url: app.globalData.serverUrl + app.globalData.apiVersion + '/service/menu',
      success: function(res) {
        var menuData = res.data.data
        console.log(menuData)
        that.setData({
          grids: menuData
        })
      }
    })
  },

  onNavigatorTap: function(e) {
    var index = e.currentTarget.dataset.index
    var item = this.data.grids[index]
    console.log(item)
    if (item.app.application == 'weather') {
      console.log('-------------')
      wx.navigateTo({
        url: '../weather/weather',
      })
    } else if (item.app.application == 'backup-image') {
      wx.navigateTo({
        url: '../backup/backup',
      })
    } else if (item.app.application == 'stock'){
      wx.navigateTo({
        url: '../stock/stock',
      })
    } else if (item.app.application == 'constellation'){
      wx.navigateTo({
        url: '../service/service?type=constellation',
      })
    } else if (item.app.application == 'joke'){
      wx.navigateTo({
        url: '../service/service?type=joke',
      })
    }
  }
})

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43746433/article/details/106436139