Day20 - [丰收款] 以Django Web框架实作永丰API线上支付模拟情境(1)

我们的丰收款主题完结了吗?

今天即使达成铁人赛的2/3赛程,在先前的篇幅已完整将每一个功能都实作出来了,原本在思考剩下的1/3是否要结束丰收款的主题,抓紧时间启动另一个Shioaji的证券主题。不过想说既然头都洗了,不如就趁这个机会,再强化一些使用Django来实作电商UI端的情境范例,所以接下来就是再把几个使用情境写一写,让整个串接的运作更有感。Shioaji就再往後摆,看後面有剩下的时间的话再来浅谈几篇了,虽然其实我蛮想试试程序交易这个议题。(好想有平行时空另一个我再写Shioaji的主题呀)

不如,继续丰收吧!

所以接下来是会以Django Web的几个页面实作情境,带到串接我们之前实作完成的永丰API Python程序码,也让有兴趣想多了解Django的实作的朋友有机会将「丰收款API + Python + Web技术」三个愿望,一次满足。

Django专用Bootstrap套件准备

首先,为了让UI可以简单快速套用自适应效果以及有美美好用的UI元件,我会使用Bootstrap作为UI Framework。当然若你们有更顺手的UI元件也可以随意选用。在Django中,有专门的Bootstrap套件可直接安装,而不需要直接复制Bootstrap的Javascript与CSS等档案进来。有django-bootstrap套件的好处是在Django Template中使用JS或CSS的引用时,是会更贴近Python套件的用法,而非操作硬生生的档案引用的作法。

首先,先使用pip进行django-bootstrap套件安装。

> pip install django-bootstrap-v5

https://ithelp.ithome.com.tw/upload/images/20211005/2013035480vGPVRMiD.png

我们因为最後要将程序上到实际的Heroku PaaS环境中,记得要再重新产生一次requirement.txt。这个是为了在做布署时,让Heroku Server知道需要连带安装的套件。

记得先退到Python Project的root folder去。

还记得语法吗? 使用pip freeze将结果导出成档案,指定到根目录下的requirements.txt (记得结尾有s)

> pip freeze > requirements.txt

以我的例子,在requirements.txt中,多出了刚刚安装的django-bootstrap-v5==1.0.5

asgiref==3.4.1
beautifulsoup4==4.10.0
certifi==2021.5.30
charset-normalizer==2.0.6
crypto==1.4.1
decorator==5.1.0
dj-database-url==0.5.0
dj-static==0.0.6
Django==3.2.7
django-bootstrap-v5==1.0.5
gunicorn==20.1.0
idna==3.2
importlib-metadata==3.10.1
Naked==0.1.31
psycopg2==2.9.1
pycryptodome==3.10.4
pytz==2021.1
PyYAML==5.4.1
requests==2.26.0
shellescape==3.8.1
soupsieve==2.2.1
sqlparse==0.4.2
static3==0.7.0
urllib3==1.26.7
zipp==3.6.0

记得,在mysite底下的settings.py中,要在INSTALLED_APPS中加上bootstrap5,才会生效喔!
例如:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bootstrap5',
    'order',
    'greetings',
]

在greetings再加个测试试试

还记得我们刚使用Django时,写了一个greetings的丑丑测试页面(index),现在我们在下面再加上一个test页面,来测试一下刚刚的Bootstrap套件。

不知道要怎麽使用Bootstrap的话,可以使用这个页面模板产生器网站:
https://generator.ws/demo/

选一个你喜欢的模版後即可简单下载,我们就把这个内容拿来做成我们要测试的Django Template页。

https://ithelp.ithome.com.tw/upload/images/20211005/20130354nmrQ7Tk5dO.png

先产生一个Template页吧

我们要使用Django的Template,才能强化View的呈现,总不能每次都只能硬刻HTML语法然後用HttpResponse传回去吧。

在我们的Django App下,例如这次是在greetings下建立一个templates目录,接着,在底下再建一个greetings目录,然後才把你要的Template HTML放在底下。

有些人会把页面直接摆在templates的目录底下,而没有多建一个与App名称相同的目录,这样基本上若你App之间没有使用相同名称的话虽不会错,但不建议这样使用。若不同的Django App使用了相同的View页面名称,会有抓取顺序错误的可能。

因此我们建立一个test.html,放置位置在:mysite/greetings/templates/greetings/test.html

内容如下:

{% load bootstrap5 %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Welcome to KummyShop</title>
    <meta charset="utf-8">
    <meta name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    {% bootstrap_css %}
    <link rel="icon" href="favicon.ico">
  </head>
  <body>
    <section class="bg-light pt-5 pb-5">
      <div class="container pb-5">
        <div class="row justify-content-center d-flex">
          <div class="col-xs-12 col-md-10 align-self-center">
            <h1 class="display-4 text-center  mb-3 mt-5">{{ title }}</h1>
            <p class="lead  text-center">{{ desc }}</p>
            <div class="justify-content-center d-flex mt-3 mb-1">
              <a class="btn btn-primary  btn-lg   mt-md-3 me-2" href="#"
                role="button">{{ buttons.0 }}</a>
              <a class="btn btn-outline-secondary  btn-lg   mt-md-3 ml-md-3"
                href="#" role="button">{{ buttons.1 }}</a>
            </div>
          </div>
        </div>
      </div>
    </section>
  {% bootstrap_javascript %}
  </body>
</html>
程序说明

上面落落长,重点几个:

  1. 我们在档案头的地方加入{% load bootstrap5 %},在meta加入{% bootstrap_css %},在body结束前加入{% bootstrap_javascript %}
  2. 中间h1大标加上{{ title }},底下p段落加上{{ desc }},两个button加上{{ buttons.0 }}{{ buttons.1 }}

前面是为了产生bootstrap5所需要的javascript与css档,後面则是我们从View届时会准备传入相关的变数,要拿来显示用。

在View中准备给Template的资料

於是我们可以在View中撰写test页所需要的资料,不过通常顺序一般规画是反过来的,照理说会先实作View中要准备什麽资料,然後才在Template里去挖洞填入。但因为刚刚先行介绍了Template後,不想跳来跳去的,但我相信聪明的读者一定可以理解。(好不负责任呀…)

我们在greetings的view.py中,新增这段:

from django.shortcuts import render

def test(request):
    context = {
        "title": "库米狗屋 ● Kummy Shop",
        "desc": "这里应有尽有,只是都缺货中,欢迎使用永丰银行信用卡唷!",
        "buttons": ["加入会员", "我先逛逛"]
               }
    return render(request, 'greetings/test.html', context)

程序说明

这里我们使用和先前直接回传HttpResponse型别回去稍有不同,我们使用了render的方式回传,把绑定Template机制的所需资料以简化的方式丢回去即可,你只需要准备好context所需要的资料,把request、template位置、context放进参数中。

如果是使用HttpResponse的方式,你还需要先将Template先用loader载入,再用loader去render()出来,上面这个作法是较为精简快速的作法,虽然如果有用到进阶一点的使用方式会有些许功能作不到。完整作法可至Django官网都看的到,这边主题不是以Django细部讲解为主,因此点到为止罗。

迫不及待了吧,之前的页面因为目的不同,为了实作串接永丰API的验证正确性为目的,都丑丑的,即将焕然一新了!

https://ithelp.ithome.com.tw/upload/images/20211005/20130354lr6QZl1XVt.png

我们可以按右键看一下HTML原始码:


<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Welcome to KummyShop</title>
    <meta charset="utf-8">
    <meta name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="">
    <meta name="author" content="">
    <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" rel="stylesheet">
    <link rel="icon" href="favicon.ico">
  </head>
  <body>
    <section class="bg-light pt-5 pb-5">
      <div class="container pb-5">
        <div class="row justify-content-center d-flex">
          <div class="col-xs-12 col-md-10 align-self-center">
            <h1 class="display-4 text-center  mb-3 mt-5">库米狗屋 ● Kummy Shop</h1>
            <p class="lead  text-center">这里应有尽有,只是都缺货中,欢迎使用永丰银行信用卡唷!</p>
            <div class="justify-content-center d-flex mt-3 mb-1">
              <a class="btn btn-primary  btn-lg   mt-md-3 me-2" href="#"
                role="button">加入会员</a>
              <a class="btn btn-outline-secondary  btn-lg   mt-md-3 ml-md-3"
                href="#" role="button">我先逛逛</a>
            </div>
          </div>
        </div>
      </div>
    </section>
  <script crossorigin="anonymous" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
  </body>

</html>

其中,可以比对一下原先插入bootstrap相关的位置

  1. meta区,产生出相关的bootstrap CSS引用
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" rel="stylesheet">
  1. body之前,产生出相关的bootstrap Javascript引用
<script crossorigin="anonymous" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

接下来实作情境页面,当然不会去实作商品页与购物车的部份(写完又30天了),所以我们会直接从「结帐页面」开始写起,把有串到永丰API的情境页实作出来。

明天继续!


<<:  Day20 - 在 XState 与 Side Effect 互动吧~ action API

>>:  勒瑰恩谈写作 (3) 饱满与跳脱

[Day 17] 定义资料 — 讲清楚很难吗?

Everybody has a different definition of the good ...

Day29练习java-多执行序

昨天是用继承Thread来执行多执行序,今天介绍另外一种方法,实作Runnable介面一样可以执行多...

{DAY 13} NumPy 学习笔记(中)

前言 今天要延续昨天的NumPy语法练习 内容会分成两大部分 将会涵盖如何提取、更新、删除阵列里的...

我们的基因体时代-AI, Data和生物资讯 Day18-基因变异的档案格式VCF

上一篇我们的基因体时代-AI, Data和生物资讯 Day17-分析定序档案格式SAM, BAM的工...

JavaScript入门 Day03_输出文字

那今天终於要来开始打code了!! 就从最基本的 Hello World开始吧 每一款程序语言最基本...