0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Twitterクローンを作ります #2 ユーザー登録機能 (1)

Posted at

Twitterクローンを作っていく企画の第2回です。

前回はクライアント側とAPI側のプロジェクトを作り、通信を確認しました。
今回はユーザー登録機能を作っていきます。

今回のコードはこちらで確認できます。

ユーザー登録画面

ユーザー登録画面を作成していきます。 client/src/views/Register.vue を追加していきましょう。

client/src/views/RegisterView.vue
<template>
    <div>Register Page</div>
</template>

<script>
export default{
    setup() {
        
    },
}
</script>

http://localhost:8080/register でアクセスできるようにルーターの設定をしていきます。

client/src/router/index.js を下記のように修正します。

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 にアクセスすることができるようになります。

スクリーンショット 2022-02-24 12.11.01.png

それでは画面を作っていきましょう。UIはUIKitを利用していこうと思っているのでインストールします。

$ cd /path/to/project/client
$ npm install uikit

client/main.js を修正してUIKitを読み込みます。

client/main.js
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 を下記のように修正します。

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>

これでなんとなく画面はできました。最上部にメニューが出てしまっていますがこれはあとでなおしましょう。

スクリーンショット 2022-02-24 14.59.57.png

ここからはユーザー登録用の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も修正しておきます。

.gitignore
server-env/
__pycache__/

それではAPIを追加していきます。

まずはmain.pyを修正します。

server/main.py
from flask import Flask
import logging

app = Flask(__name__)
app.secret_key = 'DUMMY'

app.logger.setLevel(logging.INFO)

次にユーザー登録用のAPIを追加します。

server/apis/users.py
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に送るように修正します。

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"
                        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に登録する部分とバリデーションをやっていきたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?