Создайте одностраничное приложение с помощью Vue.js и Flask

Python Flask Vue.js Vuex vue-router

В этом руководстве мы объясним, как подключить одностраничное приложение vue.js к серверной части Flask.

В общем, если вы просто хотите использовать библиотеку vue.js через шаблоны Flask, проблем нет. Однако на самом деле очевидной проблемой является то, что Jinja (движок шаблонов) также использует двойные фигурные скобки для рендеринга, как Vue.js, но это всего лишь приемлемое решение.

Я хочу другой пример. Если мне нужно создать одностраничное приложение (приложение состоит из одной страницы,vue-routerРежим истории в HTML5 и многие другие полезные функции) с vue.js, веб-сервисами, предоставляемыми Flask? Проще говоря, это должно быть так:

Фляга дляindex.htmlСлужить,index.htmlСодержит мое приложение vue.js.

Во фронтенд-разработке я использую Webpack, и он предоставляет все классные функции.

У Flask есть сторона API, к которой я могу получить доступ из своего SPA.

Я могу получить доступ к стороне API, даже когда использую Node.js для разработки внешнего интерфейса.

Звучит интересно? Итак, давайте сделаем это.

Полный исходный код, вы можете найти его здесь:

https://github.com/oleg-agapov/flask-vue-spa

клиент

Я буду использовать Vue CLI для создания базового приложения vue.js. Если вы не установили его, запустите:

$ npm install -g vue-cli

Клиентский и серверный код будут разделены на разные папки. Инициализируйте интерфейсную часть трассировки выполнения:

$ mkdir flaskvue
$ cd flaskvue
$ vue init webpack frontend

через мастер установки. Моя установка:

  1. Vue  создается только во время выполнения.

  2. Установите Vue-маршрутизатор.

  3. Проверьте код с помощью ESLINT.

  4. Выберите «Стандартный пресет» ESLint.

  5. Не пытайтесь использовать Karma + Mocha для модульного тестирования.

  6. Создавайте сквозные тесты без Nightwatch.

хорошо, тогда приходи:

$ cd frontend
$ npm install
# after installation
$ npm run dev

Это запустит установкуvue.jsзаявление. Начнем с добавления нескольких страниц.

Добавить кhome.vueа такжеabout.vueприбытьfrontend/src/componentsпапка. Они очень простые, например:

// Home.vue

<template>
<div>
<p>Home page</p>
</div>
</template>

and

// About.vue

<template>
<div>
<p>About</p>
</div>
</template>

Мы будем использовать их для правильного определения нашего текущего местоположения (согласно адресной строке). Теперь нам нужно изменитьfrontend/src/router/index.jsфайл для использования нашего нового компонента:

import Vue from 'vue'
import Router from 'vue-router'
const routerOptions = [
{ path: '/', component: 'Home' },
{ path: '/about', component: 'About' }
]

const routes = routerOptions.map(route => {
return {
...route,
component: () => import(`@/components/${route.component}.vue`)
}

})

Vue.use(Router)
export default new Router({
routes,
mode: 'history'
})

Если вы попытаетесь ввестиlocalhost:8080а такжеlocalhost:8080/about, вы должны увидеть соответствующую страницу.

Мы почти готовы построить проект и можем создать статический пакет ресурсов. Перед этим переопределим для них выходной каталог. существуетfrontend/config/index.jsНайдите следующую настройку:

index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),

изменить их на

index: path.resolve(__dirname, '../../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../../dist'),

Таким образом, HTML, CSS, JS папки /dist будут находиться в каталоге /frontend того же уровня. теперь ты можешь бежать$ npm run buildСоздайте пакет.

задняя часть

对于Flask服务器,我将使用Python版本3.6。 существует/flaskvueСоздайте новую подпапку для внутреннего кода и инициализируйте виртуальную среду:

$ mkdir backend
$ cd backend
$ virtualenv -p python3 venv

Чтобы запустить его в виртуальной среде (MacOS):

$ source venv/bin/activate

Эту документацию (http://pymote.readthedocs.io/en/latest/install/windows_virtualenv.html) необходимо активировать в Windows.

Установить в виртуальной среде:

(venv) pip install Flask

Теперь давайте напишем код для сервера Flask. Создайте файл run.py в корневом каталоге:

(venv) cd ..
(venv) touch run.py

Добавьте в этот файл следующий код:

from flask import Flask, render_template
app = Flask(__name__,
static_folder = "./dist/static",
template_folder = "./dist")

@app.route('/')
def index():
return render_template("index.html")

Этот код немного отличается от кода **"Hello World"** в Flask. Основное отличие в том, что мы указываем папку, в которой хранятся статические файлы и шаблоны/dist, чтобы отличить его от папки нашего внешнего интерфейса. Запустите сервер Flask в корневой папке:

(venv) FLASK_APP=run.py FLASK_DEBUG=1 flask run

Это запустит веб-сервер на локальном хосте:localhost:5000ВверхFLASK_APPФайл запуска на стороне сервера,flask_debug = 1будет работать в режиме отладки. Если все правильно, вы увидите знакомую домашнюю страницу, и вы закончили настройку Vue.

Между тем, если вы попытаетесь войти на страницу /about, вы столкнетесь с ошибкой. Flask выдает ошибку о том, что запрошенный URL-адрес не найден. На самом деле, поскольку мы используем History-Mode HTML5 в Vue-router, нам нужно настроить перенаправление веб-сервера так, чтобы все пути указывали на index.html. Это легко сделать с Flask. Измените существующий маршрут на следующий:

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
return render_template("index.html")

Теперь ввод URL Localhost: 5000 / о перенаправлении на index.html и Vue-маршрутизатор будет обрабатывать маршрутизацию.

Добавьте 404 страницы

Поскольку у нас есть всеобъемлющий путь, наш веб-сервер теперь с трудом перехватывает ошибки 404, и Flask направляет все запросы на index.html (страницу, которой даже не существует). Поэтому нам нужно обрабатывать неизвестные пути в приложении vue.js. Конечно, всю работу можно сделать в нашем файле маршрутизации.

Добавьте следующую строку в frontend/src/router/index.js:

const routerOptions = [
{ path: '/', component: 'Home' },
{ path: '/about', component: 'About' },
{ path: '*', component: 'NotFound' }
]

Здесь путь '*' является подстановочным знаком,Vue-routerПросто знайте любые другие пути, кроме всех других путей, которые мы определили выше. Теперь нам нужно больше творчестваNotFound.vueФайлы находятся в каталоге **/components**. Это легко попробовать:

// NotFound.vue

<template>
<div>
<p>404 - Not Found</p>
</div>
</template>

Интерфейсный сервер теперь снова работаетnpm run devПопробуйте ввести несколько адресов, бессмысленный пример:localhost:8080/gljhewrgoh. Вы должны увидеть наше сообщение «не найдено».

Добавить сторону API

нашvue.js/flaskПоследним примером руководства будет серверный API для создания и отправки клиентов. Мы создадим простой API, который будет возвращать случайное число от 1 до 100.

Откройте run.py и добавьте:

from flask import Flask, render_template, jsonify
from random import *

app = Flask(__name__,
static_folder = "./dist/static",
template_folder = "./dist")

@app.route('/api/random')

def random_number():
response = {
'randomNumber': randint(1, 100)
}
return jsonify(response)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):

return render_template("index.html")

Сначала я импортирую случайную библиотеку и функцию jsonify из библиотеки Flask. Затем я добавил новый маршрут/api/randomВернуть JSON так:

{
"randomNumber": 36
}

Вы можете проверить этот путь, просмотрев локально:локальный: 5000/API/случайный.

На этом работа на стороне сервера завершена. Время показать это на стороне клиента. Давайте изменим компонент home.vue для отображения случайных чисел:

<template>
<div>
<p>Home page</p>
<p>Random number from backend: {{ randomNumber }}</p>
<button @click="getRandom">New random number</button>
</div>

</template>
<script>
export default {
data () {
return {
randomNumber: 0
}
},

methods: {
getRandomInt (min, max) {
min = Math.ceil(min)
max = Math.floor(max)
return Math.floor(Math.random() * (max - min + 1)) + min
},

getRandom () {
this.randomNumber = this.getRandomInt(1, 100)
}
},

created () {
this.getRandom()
}

}

</script>

На данном этапе мы просто имитируем процесс генерации случайных чисел на стороне клиента. Итак, этот компонент работает следующим образом:

  1. в инициализирующих переменныхrandomNumberравно 0.
  2. В разделе методов переходимgetRandomInt(min, max)функция для возврата случайного числа из указанного диапазона,getrandomФункция будет генерировать случайные числа и назначать ихrandomNumber
  3. компонентный методgetrandomБудет вызываться после создания для инициализации случайного числа
  4. В событии нажатия кнопки мы будем использоватьgetrandomспособ получить новое случайное число

Теперь на главной странице вы должны увидеть внешний интерфейс, отображающий сгенерированные нами случайные числа. Подключим его к бэкенду.

Для этой цели я буду использоватьaxiosбиблиотека. Это позволяет нам отвечать на HTTP-запросы с помощьюJsonвернутьJavaScript Promise. Давайте установим его:

(venv) cd frontend
(venv) npm install --save axios

Открытьhome.vueопять таки<script>Добавьте некоторые изменения в раздел:

import axios from 'axios'
methods: {
getRandom () {
// this.randomNumber = this.getRandomInt(1, 100)
this.randomNumber = this.getRandomFromBackend()
},

getRandomFromBackend () {
const path = `http://localhost:5000/api/random`
axios.get(path)
.then(response => {
this.randomNumber = response.data.randomNumber
})
.catch(error => {
console.log(error)
})

}

}

Вверху нам нужно сослаться на библиотеку Axios. Тогда есть новый методgetrandomfrombackendAPI будет вызываться, а результаты извлекаться асинхронно с использованием Axios. наконец,getrandomметод должен теперь использоватьgetrandomfrombackendФункция получает случайное значение.

Сохраните файл, перейдите в браузер, запустите сервер разработки и снова обновитесь.localhost:8080. Вы должны увидеть ошибку консоли без случайного значения. Но не волнуйтесь, все в порядке. у нас естьCORS的错误意味着Flask服务器API默认会关闭其他Web服务器(在我们这里,vue.js App是在 Node.js服务器上运行的应用程序)。 если тыnpm run buildпроект, что вlocalhost:5000(например, сервер Flask), и вы увидите, что приложение работает. Однако не очень удобно создавать пакет каждый раз, когда вы вносите какие-то изменения в клиентское приложение.

Давайте воспользуемся Flask, упакованным с подключаемым модулем CORS, который позволит нам создать правило доступа к API. Плагин называется FlaskCORS, установим его:

(venv) pip install -U flask-cors

Вы можете прочитать документацию, чтобы лучше объяснить, как вы хотите, чтобы ваш сервер использовал CORS. Я буду использовать определенный метод и применять **{"origins": "*"}** ко всем маршрутам /api/* (чтобы каждый мог использовать мою сторону API). Добавьте в run.py:

from flask_cors import CORS
app = Flask(__name__,
static_folder = "./dist/static",
template_folder = "./dist")
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

Благодаря этому изменению вы можете вызывать сервер из внешнего интерфейса.

обновить:

На самом деле CORS не требуется, если вы хотите обслуживать статические файлы через Flask. Спасибо Карсону Джи за этот трюк ниже.

Идея такова. Если приложение находится в режиме отладки, оно будет проксировать только наш интерфейсный сервер. В противном случае (в производстве) просто обслуживайте статические файлы. Итак, мы делаем это:

import requests
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):

if app.debug:

return requests.get('http://localhost:8080/{}'.format(path)).text

return render_template("index.html")

Очень элегантное волшебство ✨!

Теперь с полным полным стеком** (полным стеком)приложение с вашим любимымVue.jsа такжеСборка по технологии Flask**.

постскриптум

Наконец, я хочу рассказать о том, как улучшить это решение.

Сначала используйте CORS, если вы хотите, чтобы ваш API обращался к внешним серверам. В противном случае просто используйте прокси-сервер и навыки фронтенд-разработки.

Еще одно улучшение заключается в том, чтобы избежать жесткого кодирования маршрутов API на стороне клиента. Возможно, вам нужно рассмотреть какой-нибудь словарь конечных точек API. Поэтому, когда вы меняете маршрут API, просто обновите словарь. Внешний интерфейс по-прежнему имеет действительную конечную точку.

Обычно во время разработки у вас будет как минимум 2 окна терминала: одно для Flask, а другое для vue.js. В производственной среде можно избавиться от Vue и просто запустить сервер Node.js в одиночку.

Исходный код: https://github.com/oleg-agapov/flask-vue-spa

Спасибо за прочтение!

Huizhi.com (www.hubwiz.com) Оригинальный перевод Сяочжи! ! !

Поделитесь серией учебных пособий по Vue.js 2 для семейства стволов начального уровня:

  1. Вход и улучшение Vue.js 2:Форма. Hubei wiz.com/course/v UE. …
  2. Начало работы и улучшение vuex 2:xc.hubwiz.com/course/vuex
  3. Начало работы и улучшение vue-router 2:Форма.Hubei wiz.com/course/vu и…
  4. Инженерная практика Vue.js 2:Форма. Hubei wiz.com/course/v UE to…

Кроме того, всем рекомендую вводный туториал по flask:

Объясните простым языком колбу http://xc.hubwiz.com/course/562427361bc20c980538e26f