【個人開発】Webサービス:「人生でやりたい100のこと」を作成しました(Vue.js + Python/Django)
はじめに(自己紹介)
- IT業界にずっと身を置いているものの、企業向けのシステムを扱っているということもあり、WEBサービスを自分で最初から最後まで作成したことはありませんでした。(30代後半のアラフォーです)
- Qiitaでこちら(「中年の危機」ど真ん中のオッサンがWEBサービス作ってみた)の投稿を拝見して、前々から思っていた「このままでよいのか」と「何番煎じでもよいし、ありふれたものでもよいので、なにかを作りたい(作りきってみたい)」がつながり、作成に取りかかることにしました。
何をつくろうと思ったか
- 「人生でやりたいことリスト100」 というのをgoogle検索すると、検索結果は色々でてきますが、皆さん自分のブログで書いています。ブログに書くのももちろんありだと思いますが、ブログを持っていないとか、もしくは、メンテナンスとか考慮して、自分で簡単に管理することができるとよいのではないか、と思いました。
- そこで、人生でやりたい100のこと、というタイトルでWebサービスを作成しようと思いました。
※余談:仕事をしていると、ついつい「できること」(Can)で考えがちですし、そうすべきこともたくさんあります。ただ、人生という視点で考えれば、「やりたいこと」(Want)を常に頭に置いておきたいと思っています。
【参考本】人生の100のリスト(Amazon)
こだわったこと
唯一のこだわりは、SPA(Single Page Application) として開発すること。登録や変更などで画面遷移しているのはすごく煩わしいので、自分のやりたいこと(wants)を1画面にて簡単に追加・変更等の管理ができるようにしたい。
機能・できること
簡単に言ってしまうと、Todoリストの拡張版。ただ、チェックボックスがあるような、Todoリストではなく、下記のような機能をつける。
- 100のことなので、数字つきのリスト
- 簡単(ドラック&ドロップ)に上へ下へ移動
- 達成日 / 達成時コメント が入力できる
- 達成率がグラフなどで見える
- 自分のリストのダウンロード
- やりたいこと(want)単位で、公開/非公開設定ができる(見せたくない場合は非公開にする)
- 他の人のWantsリストも参照できるので(公開のみ)、共感できるものは「いいね」ができる
使用技術
<フロントエンド>
・Vue.js / Vuex
<バックエンド>
・Python3.6 / Django2.0 / REST Framework
・MySQL
公開サイト
勉強のため、下記の2つで構築・公開
①レンタルサーバー
フロントとバックを違う環境で構築し、APIを呼ぶ
- フロント:レンタルサーバー(Vue.js)
- バックエンド:Heroku(Python + Django REST Framework + MySQL)
※Herokuは一定時間アクセスがないとスリープになるので、少し待つ場合あり
→Herokuの無料サービス終了に伴い工事中
②AWS ※ただしhttps非対応 (更新停止)
実施した勉強
Vue.jsも、Django REST FrameworkによるAPI構築もはじめてやりましたので、勉強のために下記を実施。
-
Vue.js / APIの呼出しについて
-
Qiita APIを呼び出し、キーワードによるリアルタイム検索をやってみる → Heroku
-
Python Djangoについて
-
TodoリストでCRUDを学ぶ → Heroku
-
Django REST Framework / Vue.js関連の参考URL
-
皆様のQiita投稿を参考にさせていただき、同じことをしてみる。
【参考URL】
・ Python Django チュートリアルまとめ
・ Django REST Frameworkを使って爆速でAPIを実装する
・ Django + Vue.js な開発環境を作ろう
・ Django REST framework with Vue.js
・ Django REST Frameworkでユーザ認証周りのAPIを作る
・ Django REST framework カスタマイズ方法 - チュートリアルの補足
・ サーバーサイドJavaエンジニアがVue.jsの基本を学習したときのメモ
実装のポイント
Vue.draggable:ドラッグアンドドロップで自分のWantsを移動させる
Vue.jsでドラッグ&ドロップするなら「Vue.Draggable」がおすすめらしい。
【インストール】 npm i -S vuedraggable
【参照URL】
・https://github.com/SortableJS/Vue.Draggable
・https://www.kabanoki.net/1712
・https://qiita.com/kimuray/items/d728fa1635aeacad359f
・http://sagatto.com/20171031_vuejs_sortable
<draggable v-model="wants" :element="'tbody'" :options="{handle:'.handle', animation:150, delay:150}" v-on:end="onEnd">
// ドラック&ドロップ対象のテーブルを囲む
</draggable>
<script>
import draggable from 'vuedraggable'
export default {
name: 'WantsIndex',
components: {
Chart,
draggable
},
data () {
//省略
},
computed: {
//省略
},
created () {
//省略
},
methods: {
// Vue.Draggableの移動が終わったら処理を実施
onEnd () {
var num = 0
// wantslistをループして、更新データを作成する
for (var i = 0; i < this.wants.length; i++) {
num += 1
var addnum = {
id: this.wants[i].id,
displayOrder: num
}
this.upwants.push(addnum)
}
// 更新処理を実施
axios.patch(`${process.env.API_ENDPOINT}wantsupdate/`, {
upwants: this.upwants
})
},
//省略
}
}
</script>
Chart.js:未着手・実施中・達成のステータスを円グラフ化
vue-chartjsを使用すると、簡単にグラフが作成できる。
-
インストール
npm install vue-chartjs chart.js --save
-
参照URL
https://vue-chartjs.org/guide/#introduction
http://www.sky-limit-future.com/entry/vue_use_chartjs
<template>
<div class="container">
<br>
<div class="card-group">
// 省略
<!-- カード3: 100wantsのドーナツチャート -->
<div class="card">
<Chart :chart-data="datacollection" :height="200"></Chart>
</div>
</div>
<br>
// 省略
</div>
</template>
<script>
import Chart from './Chart.js'
export default {
name: 'WantsIndex',
components: {
Chart,
draggable
},
data () {
//省略
},
computed: {
//省略
},
created () {
//省略
},
methods: {
fetchData () {
// 省略
},
// グラフデータの取得
getChartdata () {
this.datacollection = {
labels: ['未着手', '実施中', '達成'],
datasets: [
{
data: [this.getStatus('nostart'), this.getStatus('doing'), this.getStatus('done')],
backgroundColor: ['lightgreen', 'lightblue', 'lightgray']
}
]
}
},
}
}
</script>
Vue-Gravatar:グローバルに認識されるアバター
アバターアイコンは、ユーザに登録してもらいDBにて保持する形ではなく、グローバルに認識されるアバターを登録してもらい、それを表示されるようにする(e-mailアドレスでの紐付け)
v-gravatar と指定して、emailアドレスをv-bindする。
【参照URL】
https://ja.gravatar.com
https://www.npmjs.com/package/vue-gravatar
<!-- カード1: ユーザの情報(e-mailアバター、ニックネーム、likes一覧、いいね数、twitterアイコンを表示) -->
<div v-for="user in users" v-bind:key="user.id" class="card">
<div class="card-body">
<span><v-gravatar v-bind:email="user.email" :size="60" class="w-30 rounded" default-img="mm"/>
<strong>{{ user.nickname }}</strong>
</span>
<br><br>
<small><router-link to="/userlikelist"><button class="btn-sm btn-warning">Likes一覧</button></router-link></small>
<small><button v-on:click="download()" class="btn-sm btn-success">List Download</button></small>
</div>
</div>
まとめ
-
初学者としては、言語の基礎を学んだあとは、チュートリアルとして、TodoList・掲示板・Twitterのような投稿システムなどを作成してみる、という流れが多いと思いますが、その次のステップとして、それらの機能を拡張していくのが、とてもやりやすいのではないか、と作りながら思いました。
-
Django REST Framework API の便利さ、Vue.jsのおもしろさ・難しさ、などいろいろ感じることができました。
感想・その他
-
ログイン機能実装、DB連携、CRUDなどもはじめて実施しましたので、とても苦労しましたが、徐々に機能がついていき、できることが増えていくときなどとても充実感がありました。
-
今回使用した、Django REST Framework API、Vue.jsなどはじめて触りました。当然、いろいろなところでつまりながらです。仕事以外の時間はすべてこれに費やした感じがします。(約3ヶ月弱くらい)
-
やっているときは、Qiitaをめちゃくちゃ参考にさせていただきました。結果をQiitaに投稿することが1つの大きな目標になり、その目標も達成することができました。(本投稿)