Twitterクローンを作っていく企画の第2回です。
前回はクライアント側とAPI側のプロジェクトを作り、通信を確認しました。
今回はユーザー登録機能を作っていきます。
今回のコードはこちらで確認できます。
ユーザー登録画面
ユーザー登録画面を作成していきます。 client/src/views/Register.vue
を追加していきましょう。
<template>
<div>Register Page</div>
</template>
<script>
export default{
setup() {
},
}
</script>
http://localhost:8080/register でアクセスできるようにルーターの設定をしていきます。
client/src/router/index.js
を下記のように修正します。
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: '/register',
name: 'register',
component: () => import('../views/RegisterView.vue')
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
これで http://localhsot:8080/register にアクセスすることができるようになります。
それでは画面を作っていきましょう。UIはUIKitを利用していこうと思っているのでインストールします。
$ cd /path/to/project/client
$ npm install uikit
client/main.js
を修正してUIKitを読み込みます。
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import UIkit from 'uikit'
import Icons from 'uikit/dist/js/uikit-icons'
import 'uikit/dist/css/uikit.min.css'
UIkit.use(Icons)
createApp(App).use(store).use(router).mount('#app')
これでUIKitが利用できるので、ユーザー登録画面を作っていきます。
client/src/views/RegisterView.vue
を下記のように修正します。
<template>
<div class="uk-container">
<h1>ユーザー登録</h1>
<form class="uk-form-horizontal uk-margin-large" @submit.prevent>
<div class="uk-margin">
<label class="uk-form-label" for="register__display-name">表示名</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__display-name"
type="text"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__username">ユーザーID</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__username"
type="text"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__email">メールアドレス</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__email"
type="email"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__password">パスワード</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__password"
type="password"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__password-confirm">パスワード(再確認)</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__password-confirm"
type="password"
required>
</div>
</div>
<div class="uk-margin">
<input class="uk-button uk-button-primary" type="submit" value="登録" @click="onClick">
</div>
</form>
</div>
</template>
<script>
import UIkit from 'uikit';
export default {
setup() {
const onClick = () => {
UIkit.notification("hello", {status: 'danger'});
};
return {
onClick
};
},
}
</script>
これでなんとなく画面はできました。最上部にメニューが出てしまっていますがこれはあとでなおしましょう。
ここからはユーザー登録用のAPIを用意して、それを呼び出せるようにしていきましょう。
API側のプロジェクトのディレクトリ名をapiにしてしまいましたが、APIを定義するファイルをapisというディレクトリにしたいので api/apis/hoge.py
みたいになってしまうのが微妙な気がしてきました。serverに変更しましょう。
$ deactivate
$ cd /path/to/project/api
$ rm -rf ./api-env/
$ cd ..
$ mv api server
$ cd server
$ python3 -m venv server-env
$ source ./server-env/bin/activate
$ pip install -r requirements.txt -c constraints.txt
.gitignoreも修正しておきます。
server-env/
__pycache__/
それではAPIを追加していきます。
まずはmain.pyを修正します。
from flask import Flask
import logging
app = Flask(__name__)
app.secret_key = 'DUMMY'
app.logger.setLevel(logging.INFO)
次にユーザー登録用のAPIを追加します。
from flask import jsonify, request
from server.main import app
@app.route('/api/users', methods=['POST'])
def register():
body = request.json
app.logger.info(body)
return jsonify(body)
仮実装として、リクエストのbodyをログ出力しつつそのまま返却するようにしました。
画面側は入力された値をAPIに送るように修正します。
<template>
<div class="uk-container">
<h1>ユーザー登録</h1>
<form class="uk-form-horizontal uk-margin-large" @submit.prevent>
<div class="uk-margin">
<label class="uk-form-label" for="register__display-name">表示名</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__display-name"
type="text"
v-model="displayName"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__username">ユーザーID</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__username"
type="text"
v-model="username"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__email">メールアドレス</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__email"
type="email"
v-model="email"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__password">パスワード</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__password"
type="password"
v-model="password"
required>
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="register__password-confirm">パスワード(再確認)</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="register__password-confirm"
type="password"
v-model="passwordConfirm"
required>
</div>
</div>
<div class="uk-margin">
<input class="uk-button uk-button-primary" type="submit" value="登録" @click="onClick">
</div>
</form>
</div>
</template>
<script>
import { ref } from 'vue';
import UIkit from 'uikit';
import axios from 'axios';
export default {
setup() {
const displayName = ref("");
const username = ref("");
const password = ref("");
const passwordConfirm = ref("");
const email = ref("");
const onClick = () => {
var body = {
display_name: displayName.value,
username: username.value,
password: password.value,
email: email.value
};
axios.post('/api/users', body).then(resp => {
UIkit.notification("success");
console.log(resp);
});
};
return {
displayName,
username,
password,
passwordConfirm,
email,
onClick
};
},
}
</script>
今回はここまでにしましょう。
次回はDBに登録する部分とバリデーションをやっていきたいと思います。