一覧に戻る

VueとFlaskでITイベント情報を地図表示するウェブアプリを作った

#Python#JavaScript#Flask#mapbox#Vue.js

はじめに

ネットサーフィンをしていると、ITイベントポータルサイトのconnpassがイベント情報を提供するWebAPIを配信している事を知り、開催地などを地図上で表示するアプリがあれば便利なのではないかと思い制作、年始の3日間を生贄に捧げ完成。

成果物

Signpost for connpass GitHub

いわゆるSPAアプリケーションで、非同期通信で得たレスポンスを動的に地図表示します。

フレームワーク・ライブラリと選定理由

  • Flask:後述
  • Vue.js (Vue CLI):勉強中であるため、Reactよりしっくり来るため
  • Mapbox GL JS (+VueMapbox):多数の地物を表示するため動作パフォーマンスを重視した
  • BootstrapVue:神
  • OpenStreetMap(背景地図):国土地理院の基本地図よりも建物名などが見やすいから

各種ポイント

CORS制限

CORSとは、オリジン間リソース共有(Cross-Origin Resource Sharing)のこと。 簡単には、「許可を得ていない他人のウェブサイトのデータを非同期通信で持ってくるのはダメよ」、と理解している。 今回のケースでは、connpassAPIのレスポンスは、CORS制限のためフロント側で取得する事が出来ない。一度自らのサーバで受けておけばCORS制限には引っかからない。という訳で、当初はfirebaseのhostingやfunctionで対応しようと考えていたが、connpassAPIにアクセスしレスポンスを受け取るサーバをFlaskで構築する事とした。Flaskはとてもシンプルなので、今回のようになんでも良いからサーバが必要な場合に最適だと思うし、個人的に好きだから採用。

FlaskとVue.jsの環境構築

Vue.jsはnode.jsと組み合わせて使う事が多いと思います。色々調べた結果、Flaskと共存して開発出来る構成に至りました。

ルートにPythonスクリプトやherokuサーバ用ファイルを配置し、フロント側はvueディレクトリに納めてあります。以下のとおり設定する事で、Flaskは、vue/distをtemplateフォルダとして参照するようになります。


from flask import Flask, render_template, request, jsonify, make_response, send_file, redirect, url_for

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


#以下ルーティング…

APIサーバの構築

connpassAPIの仕様に沿ってアクセスし、得たレスポンスをフロントへ返すAPIサーバを以下のようにつくりました。

import urllib.request, urllib.parse
import json
@app.route('/api/')
def getApi():
    keyword_or = request.args.get('keyword_or')
    ym = request.args.get('ym')
    ymd = request.args.get('ymd')
    owner_nickname = request.args.get('owner_nickname')
    start = request.args.get('start')
    order = request.args.get('order')
    count = request.args.get('count')
    all_params = {
        "keyword_or": keyword_or,
        "ym":ym,
        "ymd":ymd,
        "owner_nickname":owner_nickname,
        "start":start,
        "order":order,
        "count":100
    }

    params = {}
    #値がNoneとなっている要素はパラメータから削除する
    for key in all_params:
        if all_params[key] != None:
            params[key] = all_params[key]


    p = urllib.parse.urlencode(params)
    url = "https://connpass.com/api/v1/event/?" + p

    with urllib.request.urlopen(url) as res:
        html = res.read().decode().replace(r"\n","")
        jsonData = json.loads(html)
        return jsonify(jsonData)

connpassAPIと同じパラメータを受け、そのままconnpassAPIに投げ、レスポンスをデコードし、jsonとして返しています。完全なる中継サーバという事です。

参考サイト

Vue.js(vue-cli)とFlaskを使って簡易アプリを作成する【後半 - サーバーサイド編】 BootstrapVue VueMapbox