1. 程式人生 > >Python+Django+小程式API+的編寫

Python+Django+小程式API+的編寫

在學習這個之前,首先要求是你們會Django框架的基礎之上,如果不會可以點選這裡學習有關Django框架的一些使用方案,在下面我將會講出有關api的簡單編寫和json資料處理過程。

api結構主要包括請求連結,入參,Django的業務邏輯處理,返回引數。一般情況下儘量使用POST請求,資料比較安全。

  1. Django的業務邏輯

    1. urls的編寫

      兩種方法的原因是1.7以前不支援path來編寫

      Django2.0.4可以使用以下方法
      from django.urls import path
      urlpatterns = [
          path('depot/'
      , get_depot), path('depot_list/', get_depot_list) ] Django1.7.0可以使用以下方法 from django.conf.urls import url urlpatterns = [ url(r'depot/$', get_depot), url(r'depot_list/$', get_depot_list) ]
    2. models建立

      就舉個簡單的栗子吧,這樣更加明確直白,這三個表個栗子,可以解決以後的多表聯合查詢問題。

      # 停車場表
      class TB_DEPOT(models.Model)
      : DE_ID = models.CharField(max_length=18, verbose_name="停車場編碼", primary_key=True) NAME = models.CharField(max_length=11, verbose_name="停車場名稱") ADDRESS = models.CharField(max_length=64, verbose_name="停車場地址") LATITUDE = models.CharField(max_length=18, verbose_name="座標(緯度)") LONGITUDE =
      models.CharField(max_length=18, verbose_name="座標(經度)") COST_1 = models.CharField(max_length=6, verbose_name="停車費用_1") COST_2 = models.CharField(max_length=6, verbose_name="停車費用_2",null=True) MAN_COST = models.CharField(max_length=6, verbose_name="日最高消費",null=True) FREE_TIME = models.CharField(max_length=6, verbose_name="免費時長",null=True) MODE_PAY = models.CharField(max_length=11, verbose_name="支付方式") START_DATE = models.TimeField(verbose_name="營業開始時間") END_DATE = models.TimeField(verbose_name="營業結束時間") STATE = models.IntegerField(verbose_name="停車場狀態") IMAGE_1 = models.ImageField(verbose_name="圖片一", upload_to=image_upload_to) IMAGE_2 = models.ImageField(verbose_name="圖片二", null=True, upload_to=image_upload_to) IMAGE_3 = models.ImageField(verbose_name="圖片三", null=True, upload_to=image_upload_to) IMAGE_4 = models.ImageField(verbose_name="圖片四", null=True, upload_to=image_upload_to) BUSI_ID = models.ForeignKey(TB_BUSINESSMAN, verbose_name="商戶編碼", on_delete=models.CASCADE) def __str__(self): return self.DE_ID class Meta: db_table = "TB_DEPOT" verbose_name = '停車場' verbose_name_plural = verbose_name # 預約表(TB_APPOINTMENT) class TB_APPOINTMENT(models.Model): APPO_ID = models.CharField(max_length=18, verbose_name="預約編碼", primary_key=True) USER_ID = models.CharField(max_length=18, verbose_name="預約人編碼") DATE = models.DateField(verbose_name='預約時間') PL_NUM = models.CharField(max_length=10, verbose_name='預約車牌', default='') APPO_TIME = models.CharField(max_length=4, verbose_name="預約時長") COST = models.CharField(max_length=4, verbose_name="預約費用") STATE = models.IntegerField(verbose_name="預約付款狀態") APPO_STATE = models.IntegerField(verbose_name='預約過期狀態', default='1') OUTPUT = models.IntegerField(verbose_name='是否入場', default='0') DEPOT = models.ForeignKey(TB_DEPOT, verbose_name="停車場編碼", on_delete=models.CASCADE) def __str__(self): return self.APPO_ID class Meta: db_table = "TB_APPOINTMENT" verbose_name = '預約' verbose_name_plural = verbose_name # 使用者表(TB_USER) class TB_USER(models.Model): OPEN_ID = models.CharField(max_length=64, verbose_name='微信唯一標識') USER_ID = models.CharField(max_length=32, verbose_name='使用者編碼') PHONE = models.CharField(max_length=11, verbose_name='使用者手機號', null=True, default='') USER_NAME = models.CharField(max_length=32, verbose_name='使用者微信名稱') USER_STATE = models.IntegerField(verbose_name='使用者狀態') def __str__(self): return self.OPEN_ID class Meta: db_table = "TB_USER" verbose_name = '使用者' verbose_name_plural = verbose_name
    3. api方法的編寫

      先看一個簡單的查詢業務案例,停車場表資訊查詢

      from django.http import JsonResponse
      from django.views.decorators.csrf import csrf_exempt
      
      #請求引數設定
      #http://localhost:8000/Api/depot/
      # 入參 無
      # 返回json資料
      
      def get_depot(request):
          if request.method == 'GET':
              try:
                  data = {}
                  depot = TB_DEPOT.objects.values()
                  data['depot'] = list(depot)
                  print(data['depot'])
                  return JsonResponse({'success': True, 'data': data['depot']})
              except Exception as e:
                  return JsonResponse({'success': False, 'data': str(e)})
      

      主要問題就是如何把把QuerySet,資料轉化成json資料,也就是Python中的字典,根據depot = TB_DEPOT.objects.values()獲取到資料物件,然後使用下面這種簡單的方法來把資料轉化成json資料,data['depot'] = list(depot),這種方法給大家解釋一下他就是把獲取到的資料物件轉化成list物件,然後反身儲存到data[‘depot’]中,完成一個簡單的轉化。

      下面這個栗子稍微有點複雜通過請求連結傳參,進行獲取資料,進行資料查詢,拼接,返回json物件。

      # 使用者預約資訊查詢 根據使用者唯一標識openid進行查詢
      # 請求示例
      # 請求示例:http://localhost:8000/Api/get_appo_over/?openId=******
      # 入參設定,需要進行openid標識傳入
      # 可選引數:STATE、PPO_STATE、OUTPUT
      # 返回使用者預約的記錄
      def get_appo_over(request):
          data = {}
          if request.method == 'GET':
              openid = request.GET.get('openId')
              state = request.GET.get('state')
              output = request.GET.get('output')
              appo_state = request.GET.get('appo_state')
              try:
                  userid = TB_USER.objects.get(OPEN_ID=openid).USER_ID
                  print(userid)
                  appo = {}
                  if state:
                      appo = TB_APPOINTMENT.objects.filter(Q(USER_ID=userid) & Q(STATE=state))
                  elif appo_state:
                      appo = TB_APPOINTMENT.objects.filter(Q(USER_ID=userid) & Q(APPO_STATE=appo_state))
                  elif output:
                      appo = TB_APPOINTMENT.objects.filter(Q(USER_ID=userid) & Q(OUTPUT=output))
                  else:
                      appo = TB_APPOINTMENT.objects.filter(Q(USER_ID=userid))
                  data['appo'] = list(appo.values())
                  i = 0
                  for a in appo:
                      print(a.DEPOT.DE_ID)
                      depot = TB_DEPOT.objects.filter(DE_ID=a.DEPOT.DE_ID).values()
                      data['depot'] = list(depot)
                      print(data['depot'])
                      data['appo'][i].update(data['depot'][0])
                      i = i + 1
                  return  JsonResponse({'success': True, 'data': data['appo']})
              except Exception as e:
                  return JsonResponse({'success': False, 'data': 0})
      

      這個介面,主要是進行預約和相對應的停車場進行查詢簡單解釋一下一些語句的用途

      openid = request.GET.get('openId')

      使用該程式碼來獲取請求連結中的引數;

      	i = 0
          for a in appo:
              print(a.DEPOT.DE_ID)
              depot = TB_DEPOT.objects.filter(DE_ID=a.DEPOT.DE_ID).values()
              data['depot'] = list(depot)
              print(data['depot'])
              data['appo'][i].update(data['depot'][0])
              i = i + 1
      

      這塊程式碼主要是對預約記錄進行解析出來,根據對應的a.DEPOT.DE_ID標識去進行停車場查詢,將得到的資料轉化,然後拼接到appo資料中,因為data[‘depot’]和data[‘appo’]都屬於是dict型別的物件,可以使用update直接把資料更新到另一個裡面注意的是如果直接更新,相同索引的值都會被替換掉,所以使用之前先對資料進行處理。

    4. 小程式端的請求方法

      var that = this
          wx.request({
            url: 'http://127.0.0.1:8000/Api/get_appo_over/?openId=' + app.gloabData.openid + '&state=0', method: 'GET',
            // url: 'https://api.songshao.site/Api/get_appo_over/?openId=' + app.gloabData.openid + '&state=0', method: 'GET',
            header: { 'content-type': 'application/json,charset=utf-8' },
            success: function (res) {
              console.log(res.data.data)
              if (res.data.data.length == 0) {
                that.setData({
                  num: 0
                })
              } else {
                that.setData({
                  num: 1,
                  appo: res.data.data,
                })
              }
      
            }, fail: function (res) {
              wx.showToast({
                title: '伺服器開了小差,下拉重新整理一下',
                icon: 'waring',
                duration: 3000
              })
            }
          })
      

      小程式使用wx.request來請求api,在url中編寫連結地址和對應的引數,請求method一般儘量使用post,請求頭設定 header: { ‘content-type’: ‘application/json,charset=utf-8’ },成功之後返回資料處理請求成功資料如下:

      {"success": true, "data": [{"APPO_ID": "684407", "USER_ID": "8208225", "DATE": "2018-12-25", "PL_NUM": "\u9655A88888", "APPO_TIME": "10", "COST": "0.5", "STATE": 1, "APPO_STATE": 1, "OUTPUT": 0, "DEPOT_id": "20181215002", "DE_ID": "20181215002", "NAME": "\u5c1a\u54c1\u7f8e\u5730\u57ce\u4e8c\u671f", "ADDRESS": "\u9655\u897f\u7701\u897f\u5b89\u5e02\u96c1\u5854\u533a\u9526\u4e1a\u8def92\u53f7", "LATITUDE": "34.34627", "LONGITUDE": "108.93984", "COST_1": "5", "COST_2": "6", "MAN_COST": "50", "FREE_TIME": "0.5", "MODE_PAY": "\u7535\u5b50\u652f\u4ed8", "START_DATE": "00:00:00", "END_DATE": "23:59:00", "IMAGE_1": "index/static/upload_image/47735b874b494483b1ab1149b1b6d84d/\u5c1a\u54c1.jpg", "IMAGE_2": "index/static/upload_image/d03235beb44548de9cab02041ba2d511/\u5c1a\u54c1.jpg", "IMAGE_3": "index/static/upload_image/14545c2c9f4a4e2ebf392a3fe04bc1af/\u5c1a\u54c1.jpg", "IMAGE_4": "index/static/upload_image/4bb82db280584fa6a6e4f91fde65f7e5/\u5c1a\u54c1.jpg", "BUSI_ID_id": "20181215001"}, {"APPO_ID": "9276129", "USER_ID": "8208225", "DATE": "2018-12-25", "PL_NUM": "\u9655E88888", "APPO_TIME": "10", "COST": "0.5", "STATE": 1, "APPO_STATE": 0, "OUTPUT": 0, "DEPOT_id": "20181215002", "DE_ID": "20181215002", "NAME": "\u5c1a\u54c1\u7f8e\u5730\u57ce\u4e8c\u671f", "ADDRESS": "\u9655\u897f\u7701\u897f\u5b89\u5e02\u96c1\u5854\u533a\u9526\u4e1a\u8def92\u53f7", "LATITUDE": "34.34627", "LONGITUDE": "108.93984", "COST_1": "5", "COST_2": "6", "MAN_COST": "50", "FREE_TIME": "0.5", "MODE_PAY": "\u7535\u5b50\u652f\u4ed8", "START_DATE": "00:00:00", "END_DATE": "23:59:00", "IMAGE_1": "index/static/upload_image/47735b874b494483b1ab1149b1b6d84d/\u5c1a\u54c1.jpg", "IMAGE_2": "index/static/upload_image/d03235beb44548de9cab02041ba2d511/\u5c1a\u54c1.jpg", "IMAGE_3": "index/static/upload_image/14545c2c9f4a4e2ebf392a3fe04bc1af/\u5c1a\u54c1.jpg", "IMAGE_4": "index/static/upload_image/4bb82db280584fa6a6e4f91fde65f7e5/\u5c1a\u54c1.jpg", "BUSI_ID_id": "20181215001"}]}
      

      首先需要說明小程式請求之後會把json資料預設存放方到data裡面,這塊本省還有一個data,所以定位時就需要用res.data.data定位資料,像這個json資料有兩條,在頁面顯示時可以用for迴圈輸出資料

      <view class='content_view' wx:for='{{appo}}' wx:key>
            <view class='header'>
              <text class='l_text'>{{item.DATE}}</text>
              <text class='r_text'>未進場</text>
            </view>
            <view class='header_content'>
              <view  class='header_text'>
                <text>{{item.NAME}}停車場</text>
              </view>
              <view class='text_view'>
                <image class='image_style' src='../../resource/image/ding_wei_1.png'/>
              <text class='text_view_text'>{{item.ADDRESS}}</text>
                </view>
              <view class='text_view'>
                <image class='image_style' src='../../resource/image/car.png'/>
                <text class='text_view_text'>預約車牌為:{{item.PL_NUM}}</text>
              </view>
              <view class='text_view'>
                <image class='image_style' src='../../resource/image/time.png'/>
                <text class='text_view_text'>剩餘時長:{{item.APPO_TIME}}</text>
              </view>
              <button class='btn'>續費</button>
            </view>
            
          </view>
      

      在迴圈中可以通過定義的資料物件appo,去迴圈,因為迴圈使用的是它的array(),因為json物件有兩條所以迴圈兩次,輸出,每次遍歷陣列物件是可以使用item.屬性名,來獲取相應的資料,顯示結果如下圖所示

    在這裡插入圖片描述

    如果出現這種結果就說明你的小程式成功了!