软件测试精进之路数据蛙数据分析每周作业百人计划

小复盘:Vue+Flask实战Web应用(未完待续)

2018-12-28  本文已影响26人  cynthia猫

本文主题

简单聊一聊实战中的一些体会好了,主要聊到如下主题,您感兴趣就随便看看:

〇、前提

项目相关环境
前端:http://127.0.0.1:8010
后端:http://127.0.0.1:8089

一、路由的秘密

  1. 先说一个现象

当我们在前端页面

http://127.0.0.1:8010/manage/flowerManage/proGather/list

进行某个操作时,在调试窗口看到它访问了后端接口

http://127.0.0.1:8010/api/flower/proGather/list

那么试试直接在Postman这种接口测试工具里输入该接口,得到了对应结果。
那么我们知道,后端其实是在8089端口启的服务呀?那我们再来试试在Postman中访问这个接口:

http://127.0.0.1:8089/api/flower/proGather/list

哈哈,出错啦。不过注意到没有,虽然postman上显示的status还是200,但是返回的Response里面有这么一行:

raise NotFound()\nwerkzeug.exceptions.NotFound: 404 Not Found: The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.

2.为什么呢?

先说说为什么通过前端服务端口,能访问到后端服务的api。首先前端服务应该是做了路由的,所以会转到真正的后端接口上去。(如果说的不对欢迎指出)

路由其实蛮重要的,不仅仅是在我们写Web应用的时候。比如nginx就有提供专门的代理服务,这些以后有时间可以多多了解。

接下来看看后端为啥没有访问成功,这个是和我们的配置息息相关的。因此会放到后面“Vue-cli配置文件”的部分详细解释清楚,先来说下针对我这个项目,如何可以访问成功:

http://127.0.0.1:8089/flower/proGather/list

去掉路径里面的api,就可以了……

(其实路由也还没写完,还想写下前端的路由。。)

二、蓝图

概念大家都懂了哇?说一下怎么用。
create_app的定义里面注册就好了,然后可以指定对应的url_prefix

对于一个Web应用,你可以图省事只使用一个蓝图,也可以使用多个蓝图分开不同的模块方便管理,记得注册就好了,在__init__.py文件中,写了相关代码如下:

def create_app():
    app = Flask(__name__)
    app.config.from_object(BaseConfig)
    app.logger.addHandler(config_log())  # 初始化日志
    BaseConfig.init_app(app)
    moment.init_app(app)

    db.app = app
    db.create_all()

    login_manager.init_app(app)
    scheduler.start()  # 定时任务启动

    # 注册多个蓝图模块
    from app.admin import admin_module
    from app.flower import flower_module
    app.register_blueprint(admin_module, url_prefix='/admin')
    app.register_blueprint(flower_module, url_prefix='/flower')

    return app

那么再来看看蓝图模块是怎么写的呢?
目录结构是这个样子的(手工敲的,没有用目录生成的那种app,顺便求一下哪个生成目录结构好用啊):

app
    -admin
        __init__.py
        admin_manage.py
    -flower
        __init__.py
        flower_manage.py
    __init__.py

看下admin目录下的两个文件;flower目录下也是类似的

app/admin/__init__.py

from flask import Blueprint
admin_module = Blueprint('admin_module', __name__)
from . import admin_manage
app/admin/admin_manage.py

from . import admin_module

@admin_module.route('/admin/add', methods=['POST'])
def add_user():
    pass

好啦,照葫芦画瓢,你也会注册蓝图模块了!

三、理解Vue的单页面应用

很久以前用html做过网站,所以一直有一个惯性思维,觉得点击网页上的超链接跳来跳去的,就一定是在不同的页面间切换。

所以一开始也按照这个思路来学习Vue,看到别人案例中,有一个个的Vue文件,想当然的就理解成对应的页面了,后来才发现并非如此。

组件

Vue中有一个很重要的概念就是组件!官网都是这么介绍组件的:

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
<div id="components-demo">
  <button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })

组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

你可以将组件进行任意次数的复用。

罗里吧嗦一大堆,那么它和单页面应用之间有什么联系?

(未完待续,发现写文章想解释的清楚一点,还真得多花时间,我尽量在本周内更新完这篇)

四、Vue-cli配置文件

在这个项目里,前端使用了Vue-cli脚手架。
如果你也直接用Vue-cli创建一个vue项目的话,可以在config目录下看到好几个.js文件,就是配置文件啦。
如果你是网上找来的项目,可能会略有不同,不过内容上都是类似的。

这次我们就来看看index.js文件里的部分内容吧,由于把配置详解一遍很花时间,所以我们就聚焦一点,来揭开第一部分接口调用路径的谜底!
当然,有些项目的配置不一定保持了初始的名字,总之是含有module.exports = {这行代码的配置文件就对了!

我这里是这样配置的:

module.exports = {
    lintOnSave: true,
    productionSourceMap: false,
    chainWebpack: (config) => {
        config.resolve.alias
            .set('~', resolve('src'))
    },
    devServer: {
        host: '127.0.0.1',
        port: 8010,
        proxy: {
            '/api/': {
                target: 'http://127.0.0.1:8089',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    },
    css: {
        loaderOptions: {
            css: {
                localIdentName: process.env.node_env == 'production' ? "[hash]" : '[path]_[name]_[local]_[hash:base64:5]',
                camelCase: 'only'
            },
            sass: {}
        },
    }
};

首先看下这个devServer.proxy.changeOrigin,它是为了解决跨域问题的一个设置。
changeOrigin: true, //开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,这样服务端和服务端进行数据的交互就不会有跨域问题

那什么是跨域?

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域,如下例子:
域名
主域名不同 http://www.baidu.com/index.html –>http://www.sina.com/test.js
子域名不同 http://www.666.baidu.com/index.html –>http://www.555.baidu.com/test.js
域名和域名ip http://www.baidu.com/index.html –>http://180.149.132.47/test.js
端口
 http://www.baidu.com:8080/index.html–> http://www.baidu.com:8081/test.js
协议
 http://www.baidu.com:8080/index.html–> https://www.baidu.com:8080/test.js
备注
 1、端口和协议的不同,只能通过后台来解决
 2、localhost和127.0.0.1虽然都指向本机,但也属于跨域

综上,我目前的设置前后端的端口不一样,也算是跨域了,因此就要设置成true啦!

接着看下这段:

 proxy: {
            '/api/': {
                target: 'http://127.0.0.1:8089',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
      }

vue-cli的这个设置来自于其使用的插件http-proxy-middleware,github地址如下:
https://github.com/chimurai/http-proxy-middleware
官网文档中有这么一句:

proxy('/api', {...}) - matches paths starting with /api

这就说明,当我们的路径中含有/api的时候,就会匹配到这里对应的配置啦。

那么pathRewrite是干啥的呢?文档解释如下:
option.pathRewrite: object/function, rewrite target's url path. Object-keys will be used as RegExp to match paths.
并且给出示例:

// rewrite path
pathRewrite: {'^/old/api' : '/new/api'}

// remove path
pathRewrite: {'^/remove/api' : ''}

// add base path
pathRewrite: {'^/' : '/basepath/'}

// custom rewriting
pathRewrite: function (path, req) { return path.replace('/api', '/base/api') }

而我们的配置中有写pathRewrite: { '^/api': '' },因此proxy时要把路径中的/api去掉。
OK,那么整体来解释一下devServer这段配置的意思!

devServer: {
        host: '127.0.0.1',
        port: 8010,
        proxy: {
            '/api/': {
                target: 'http://127.0.0.1:8089',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }

首先,127.0.0.1:8010过来的请求,如果路径中含有/api,就会被路由到127.0.0.1:8089上去,并且把路径中的/api去掉。
也就是说,当我们在前端访问了一个这样的接口:

http://127.0.0.1:8010/api/flower/proGather/list

实际上对应的是后端这个接口:

http://127.0.0.1:8089/flower/proGather/list

再来回到开头的问题上来,为什么使用postman访问http://127.0.0.1:8089/api/flower/proGather/list会报404的错误?这下你就清楚了吧!

上一篇 下一篇

猜你喜欢

热点阅读