React講座 コンポーネントとProps

React コンポーネントとprops

コンポーネントにより UI を独立した再利用できるパーツに分割し、パーツそれぞれを分離して考えることができるようになります。今回はコンポーネントという概念を理解できることを目標にしましょう。 関数コンポーネントとクラスコンポーネント コンポーネントを定義する最もシンプルな方法は JavaScript の関数を書くことです: この関数は、データの入った”props”プロパティというオブジェクトを引数として受け取り、React要素を返します。これがコンポーネントになります。 プロパティは親からもらうプレゼントをイメージしてください。そのプレゼントには何かのデータが入っていることをイメージしましょう。※propsは常に親から子です。子のコンポーネントから親コンポーネントにpropsが渡ることはありませんので覚えておきましょう。 classを使ってコンポーネントを定義することもできます。 細かいコンポーネントの構成については次回以降に説明をするので、再度コンポーネントの概念について理解を深めていきましょう。 コンポーネントのレンダー ここまでは、DOMのタグを使うReact要素のみを使いました。 しかし、要素はユーザー定義のコンポーネントを使用することもできます。 React がユーザ定義のコンポーネントを見つけた場合、JSX に書かれている属性と子要素を単一のオブジェクトとしてこのコンポーネントに渡します。このオブジェクトのことを “props” と呼びます。 例えば以下のコードではページ上に “Hello, Sara” を表示します: この例で何が起こるのかおさらいしてみましょう。 補足: コンポーネント名は常に大文字で始めてください。 React は小文字で始まるコンポーネントを DOM タグとして扱います。例えば、<div /> は HTML の div タグを表しますが、<Welcome /> はコンポーネントを表しており、スコープ内に Welcome が存在する必要があります。 コンポーネントを組み合わせる コンポーネントは自身の出力の中で他のコンポーネントを参照できます。これにより、どの詳細度のレベルにおいても、コンポーネントという単一の抽象化を利用できます。ボタン、フォーム、ダイアログ、画面:React アプリでは、これらは共通してコンポーネントとして表現されます。 例えば、Welcome を何回もレンダーする App コンポーネントを作成できます: 典型的には、新規の React アプリは階層の一番上に単一の App コンポーネントを持っています。しかし、既存のアプリに React を統合する場合は、Button のような小さなコンポーネントからボトムアップで始め、徐々にビューの階層構造の頂上に向かって進んでいってもよいでしょう。 コンポーネントの抽出 では、コンポーネントがどのように構成されるか分かったところで、どの段階でコンポーネントにするか悩みますよね。しかし、コンポーネントをより小さなコンポーネントに分割することを恐れる必要はありません。 例えば、この Comment コンポーネントについて考えましょう: これは props として author(オブジェクト)、text(文字列)、および date(日付)を受け取り、ソーシャルメディアサイトにおける … Read more

React講座 要素のレンダー

React要素の使い方

要素(エレメント)とは React アプリケーションの最小単位の構成ブロックです。 ブラウザのDOM要素と異なり、React要素は単純なオブジェクトになり、簡単に作成されます。React DOMがReactエレメントを把握してそれに従いDOMを更新する作業を担当することになります。 補足: 要素のことを、より広く知られている概念である “コンポーネント” と混同する人もいるかもしれません。コンポーネントについては次の章で説明します。要素とはコンポーネントを “構成する” ものです。次に進む前にこの章を読んでいくことをお勧めします。 要素を DOM としてレンダーする HTMLファイルの中に<div>要素があったとしましょう。 最初の記事で説明したようにindex.htmlにはrootの要素が一つだけありましたね。 ここにReactDOMがすべてのReactのアプリケーションを管理することになるのでルートのDOMノードと呼ぶことにしましょう。 Reactだけで構築されたアプリケーションはDOMノードを一つだけ持ちます。既存のアプリにReactを組み合わせて使いたい場合は独立したDOMノードを複数使用することも可能です。 React 要素をルート DOM ノードにレンダーするには、まず ReactDOM.createRoot() に DOM 要素を渡し、root.render() に React 要素を渡します。 このコードにより”Hello World”が表示されます。 レンダーされた要素の更新 react要素はイミュータブルです。※イミューン(Immune:変更できない) 一度作成された要素の子要素や、属性などを変更することはできません。 今の学習段階でUIを更新する方法は新し要素を作成してroot.render()に渡すという事になります。 以下の例で秒刻みに動く時計の例についてみてみます。 実際の例を見てください。 この例ではsetInterval() のコールバックから root.render() を毎秒呼び出しています。 補足: 上記のコードは例として記載したものであり、実際にはroot.render()を呼び出すことは1度のみ行う事が通常になります。次の章では、上記のコードをstate付きのコンポーネントへとカプセル化する方法を学びます。飛ばさないようにしましょう。 React は必要な箇所のみを更新する ReactDomは要素とその子要素を以前のものと比較しています。その比較の際に差があった場合、必要な部分のみのDOMの更新を行うことになります。 下記の例では時間の変わる要素の部分のみ更新されていることが分かりますね。 このように必要な部分だけリアクティブに要素が変わることでユーザーにインタラクティブなインターフェイスを提供することができますね。

React講座 JSXの使い方

React JSXの使い方

ではReactの仕組みを理解したところでReactのテンプレートシンタックスのJSXを理解していきましょう。 JSXはこのように書くことができます。ストリングでもないのでクオートで囲う必要もありません。 JSXを使わない方法もありますが、Reactを使う上ではJSXを是非使っていきたいです。 JSXはReactのエレメントを作成して、そこからDOMに変換されるようになります。 JSXを使う理由 Reactはイベントへのリスポンスや状態の変化を感知してユーザー側に表示するデータをリアクティブに作成することができます。 Reactの強みでもあるのがこのロジックとマークアップ(HTML)を同じファイルに記述できることです。ファイルが別々でないので一目で見ただけで何がユーザー側に表示されるか理解しやすいです。 この概念をコンポーネントと呼びます。 JSXに式を埋め込む では、次の例を見てみましょう。 nameという変数を宣言し、中括弧{}に入れることでJSX内で使用することができます。 この方法を使うことで、計算式の2+2やオブジェクト(例:user.name)を使うことができます。 JSXは長く記載する場合もあるので()で囲むようにするとよいです。 JSX自体を式として使う 先ほどはJSXに変数を入れる方法を紹介しました。 さらに、JSX自体も式としてif文やforループの文で使用することができます。 ReactがJSXを読み込む際にコンパイルされ普通のJavaSxriptに変換されるようになります。 JSXで属性を指定する 文字列リテラルを属性として指定するために引用符(クオーテーション)を使用できます。 これでHTMLの属性(attribute)にストリングの値を入れてあげることができます。 また、属性に JavaScript 式を埋め込むために中括弧を使用することもできます。これでダイナミックなデータを流し込むことができますね。 注意しておきたいこと JSXはHTMLよりもJavaScriptに近いものになります。ですのでHTMLの属性にclassを入れたい場合はJavaScriptのclassと干渉することを防ぐためにclassNameを使うことになります。 JSXで子要素を指定 タグが空の場合は、XMLのように/>でタグを閉じることができます。 もちろんJSXのタグに子要素(HTMLのタグ、エレメント)を入れることができます。 JSX はインジェクション攻撃を防ぐ JSX にユーザの入力を埋め込むことは安全です: React DOMはJSXに埋め込まれた値をレンダー前にエスケープします。 →エスケープとは、HTML上で特殊文字を期待通りに表示するために施す処理のことです。 →特殊文字に指定されている文字は、割り当てられている記号を記述することで表示できます。 →例えば、<は<であったり、©は©など、特殊文字には必ず該当する記号が割り当たっています。 このため、XSS攻撃の防止になります。 JSXはオブジェクトの表現になる ReactがJSXをコンパイルする流れを見てみましょう。 下記の二つの例は同じものになります。 ①JSXの例 ②JSXを使わない例 上記のコードをReactのcreateElementメソッドで下記の様なオブジェクトを作成することになります。 このようなオブジェクトはReact要素(エレメント)と呼びます。Reactがこれらのオブジェクトを読み取り、必要に応じてDOMを構築し常にリアクティブなデータをユーザーに’届けるようになります。 では、次回は要素のレンダーについて学んでいきましょう。

Django REST APIを公開

DjangoAPI-Demo

皆さん、こんにちは。 今日は、PythonのウェブフレームワークDjangoで作成したREST APIを公開するので是非使ってみてください。 APIの概要 このAPIはコールセンターをイメージしたDBを構成し、CRUD操作(Create,Read,Update,Delete)を可能にしたAPIです。 もう一つにトークン認証でログインしたユーザーのみアクセスできるAPIもあります。 そちらは、81番ポートからアクセスしてください。今回はトークン認証の不要なAPIのみ紹介します。 使えるAPI 利用可能なAPI http://172.104.81.40/api/ このURL(URI)にアクセスすると、下記のように各URLからAPIにアクセスできます。 Office:オフィス情報のAPIです。 Staff:従業員のAPIです。Officeの情報が紐づいています。 Tickets:お客様からのコール情報に他のテーブル(スタッフ、店舗情報、チケットカテゴリ)が紐づいています。 Ticket-Categories:コールのカテゴリ情報です。 Company:企業情報です。 StoreS:各企業の店舗情報です。 Customer-contact:お客様の連絡先です。 Djangoセットアップの手順 下記のURLにソースコードがアップロードされているので自由にクローンして使ってください。 https://github.com/TraitOtaku/Django-TicketAppAPI Gitを使ってクローンからセットアップまでの手順です。 モデルの内容 各アプリのmodels.pyを参照して受け入れるデータタイプとデータが必須かどうかを確認してください。 blank=True, null=Trueの場合はデータがなしでもOKです。 シリアライザーの内容 各アプリのSerializers.pyが先ほどのDBとコミュニケーションをとるmodels.pyをシリアル化してAPIの役目をします。チケットの例でいうとReadのGETリクエストが来たときとその他のリクエストで別々のリスポンスを返すようにしています。その設定はViews.pyで行いますが、APIの内容はここで決めます。 https://github.com/TraitOtaku/Django-TicketAppAPI/blob/master/tickets/serializers.py UIからデータを操作してみる では、実際にDjangoのAPIのUIを使用してデータを操作してみましょう。 http://172.104.81.40/api/tickets/ 上記のJSONデータを入れてあげると、DjangoからAcceptのリスポンスが返されてデータが追加されました。 レコードの更新と削除 先ほど作成したレコードはIDが1で作成されました。このデータにアクセスするには下記のようにURLの最後にIDを追加すればOKです。 http://172.104.81.40/api/tickets/1/ そうするとDELETEのオプションと下記にPUTとPATCHのオプションが追加されるのでそこからレコードを削除するなり修正するなりできます。

複数のDjangoのアプリを同じサーバーからデプロイする方法

複数のサイトを一つのサーバーからデプロイする方法

皆さん、こんにちは! Djangoのアプリはデプロイできたけど、複数のDjangoアプリを同じサーバーからデプロイしたいという方に是非読んでほしい記事です。 Djangoのアプリのデプロイができたら複数のDjangoアプリをデプロイすることも特に難しいことはないので是非チャレンジしてください。 今日の環境 Ubuntu 22.04のインストールされたサーバー SSHで接続できる状態 Djangoアプリが一つデプロイされている状態 詳しいDjangoのデプロイについては下記の記事から進めてください。 Djangoがデプロイができたらこの記事に戻ってきましょう! 今日はticketauthという名前のアプリをデプロイします。 あと、Linuxのコマンド(Bash)が少しわかっている方が理解しやすいです。 今日のスタック 今日は上記の記事で紹介したNginxをウェブサーバー、GunicornをWSGIのアプリケーションサーバーとして使用したものに2つ目のDjangoを追加するようにします。 Djangoがデプロイできた状態でさらにもう一つDjangoのアプリを同じサーバーからデプロイするような形で進めます。 ユーザーがアクセスする方法 同じサーバーに複数のドメイン(なんとか.comとか)でそれぞれのDjangoアプリに誘導する方法もあります。 今日は今使っている80番のポートがあるので81番のポートを開けてユーザーがIPアドレスから2つ目のDjangoアプリにアクセスできるようにします。 Djangoアプリをアップロード では、自身で作成したDjangoアプリ(2つ目)をアップロードしましょう。 場所はどこでもよいですが、前回はhome/user名の直下に置いたので同じ階層に置きます。 ticketapiが前回デプロイしたものです。 tikcetapiAuthが今アップロードしたばかりのものでこれからデプロイします。 下準備 では、前回の記事を参考にしながら、下記のDjangoの下準備を進めましょう。 Django用に仮想環境を作成 仮想環境をアクティベート pipでDjangoプロジェクトのライブラリをインストール Settings.pyのコンフィグ設定 DBの設定(PostgreSQLに接続) Staticファイルの扱い データベースのマイグレーション スーパーユーザーの作成 collectstaticの実行 ファイヤーウォールの設定 Djangoのテストサーバーでテスト Gunicornを使ってテスト Gunicornの設定ファイルの作成 ではDjangoのテストサーバーでIPアドレスからアクセスして問題がないようでしたら、2つ目のDjango用に新しくGunicornの設定ファイルを作成します。 今回使うのは、SocketファイルとServiceファイルです。 Gunicornのソケットファイルの作成 前回の記事でgunicorn.socketファイルを作成しているので2つ目のアプリ用と分かるような名称にして.socketファイルを作成します。 中身はこんな感じになります。 Gunicornのサービスファイルの作成 サービスファイルはGunicornがDjangoのファイルをプロセスするためのコンフィグファイルになります。 テストサーバー(python manage.py runserver)の本番用という事ですね。 では下記のコマンドでサービスファイルを作成します。 中身はこのような感じです。 次に下のコマンドでGunicornソケットを実行します。これで自動でソケットファイルが作成されます。 次にこれをEnable(実行:オン)にします。これで、ソケットに接続された際にsystemdが自動でgunicorn.socketを実行して処理してくれるようになります。 Gunicorn Socketファイルを確認しよう gunicorn.socketをアクティブにします。 … Read more

複数のウェブサイトを一つのサーバーからデプロイする

複数のサイトを一つのサーバーからデプロイする方法

皆さん、こんにちは。 今日は今まで習ってきたウェブサイトのデプロイの仕方をちょっと工夫してみます。 特に、ドメインはいらないけど、複数のポートを開けておいて、各ポートに応じたウェブサイトがユーザーに届けられるようにしたい!という時を想定しています。 下記に、例を挙げます。 社内のアプリケーションで、複数のアプリケーションを同じサーバーからデプロイしたい。 プログラムのポートフォリオを同じサーバーにまとめておきたい。 しかし覚えておきたいのはIPアドレスでユーザーがアクセスできるという事は、HTTPSにできない。つまり、ユーザーとやり取りするデーターが暗号化できないので個人情報のあるフォーム等を使う事は絶対に避けましょう。 もし、ドメインを購入して、ドメインごとに対応したウェブサイトを同じサーバーからデプロイすることもできるので、その場合は別の記事を参考にしてください。 今日の目的 Ubuntuサーバーから2つのサイトをデプロイさせる。ユーザーはIPアドレスとポートを見てそれぞれのサイトにアクセスできるようにする。 今日の環境 Ubuntu 22.04 下準備 では、下記の記事にnginxのセットアップの仕方が記載されているので、まずはそちらを見てください。 この記事の通りに進めてIPアドレスでNginxのデフォルトのページが見れるところまで進めてください。 サーバーブロックの設定 ここも前回の記事を参考に一つ目のサイトとなるファイルを作成していきます。 詳しい説明は前回の記事を参考にしてください。 各ウェブアプリケーション事でサイトを作成します。まずは一つ目のサイトをasameshisoft.comと名前を付けてそのフォルダーを作成します。 (今回はドメインは購入しないのでIPアドレスで参照します。) ランディングページを作りましょう。 今回はテストだけなので適当にテキストを書いておきます。 nginx Nginxの指定したsites-enabledディレクトリにリンクさせます。 nginxのテストをします。sucessと出れば成功です。 Nginxのサービスをリスタートします。 これでポート80をリッスンするサイトが完成しました。 2つ目のサイトのポートを開ける 今回はポート80と81を使ってサイトを公開します。ポート81はまだ何もしていないのでこれから設定していきましょう。 2つ目のサイトを設定 先ほどと同じことを繰り返します。 ポートを81にして、サイト名(ただの名称)をasameshiapp.comにした場合です。 では2つのブラウザをオープンしてサーバーのIPとポートを指定してエンターします。 172.105.218.191:80 172.105.218.191:81 皆さんも自分のサーバーのIPで同じことを行い、それぞれのHTMLが返ってきたら成功です! ではお疲れさまでした。

UbuntuサーバーにNginxをインストールしよう

Install-nginx-on-Ubuntu

今日は前回作成した仮想マシンにインストールしたUbuntuサーバーにNginxをインストールしていきます。 仮想マシン(VirtualBox)にUbuntuサーバーをインストールする方法かこちらからどうぞ。 Nginxとは Nginx(エンジンエックス)はApacheと同じで、世界で最も使われているウェブサーバーのうちの一つです。 Ngnixは、軽量で、大規模なウェブサイトにも使えるエンタープライズレベルのアプリケーションになります。 今日の目的 この記事では、Ubuntuサーバー22.04にNginxをインストールして、ファイヤーウォールの設定、Nginxののプロセスを管理、そしてサーバーブロックを設定する方法を説明します。 準備しておくこと Ubuntuサーバーのある環境(今回はバージョン22.04) Ubutnuユーザーのログイン情報 必要に応じてドメインネームの取得 Nginxのインストール NginxはUbuntuのデフォルトのリポジトリで取得可能なためそこから簡単にインストールできます。今回はサーバーを設定したばかりなのでローカルパッケージをアップデートして最新のパッケージにアクセスできるようにしておきます。 Nginxの際にDo you want to continue?と聞かれるのでY(イエスの意味)を入力してエンターします。 ファイヤーウォールの設定 Nignixをテストする前にファイヤーウォールのソフトウェアを設定してNginxがサービスにアクセスできるようにします。 先ほどNginxをインストールした際にNginx自体がサービスとしてufw(Uncomplicated Firewall)に登録されています。 まずは、ufwに登録されているアプリケーションを一覧で見てみましょう。 アウトプットから見てわかるようにNginxから3つのプロフィールが作成されていることが分かります。 Nginx Full: ポート 80 (通常, 暗号化されていない)とポート 443 (TLS/SSL 暗号化されたトラフィック) Nginx HTTP: ポート80だけ Nginx HTTPS: ポート443だけ 今回はポート80しか使わないので下記のコマンドでポート80だけ開けておきます。もちろん、プロダクションの場合はHttps://を使うのでポート443を開けることになります。 このコマンドで、現在のステータスを確認しましょう。 もしStatusがinactiveとなっている場合はファイヤーフォールがアクティブになっていないのでこのコマンドでファイヤーオールを起動させます。 再度ステータスを確認するとアクティブになっていることが分かり、HTTPのファイヤーウォールも設定されていることが分かりますね。 ウェブサーバーの設定 Nginxをインストールした時点で、自動でウェブサーバーが起動して使える状態になっているはずです。 念のために確認しておきましょう。 アウトプットを見てわかるように、アクティブになっていることが分かります。 これでサーバーのIPアドレスにアクセスするとNginxのデフォルトのページが見れるはずです。 まずは、サーバーのIPアドレスを見つけましょう。 ifconfigのコマンドが使えない場合は、このコマンドでnet-toolをインストールしてくださいというメッセージが出ますね。インストールし再度ifconfigのコマンドを実行します。 もしVirtualBoxを使っている人は仮想マシンのSettingからNetworkにいき、Bridged Adapterになっていることを確認しましょう。 使用しているネットワークのインターフェースにもよりますが、enp0s3の方のinetが192.168.0.186になっていることが分かります。loの方はローカルの方なので関係ないです。 もしレンタルサーバーとかを使っている方はパブリックIPが分かるはずなのでそれを自身のブラウザに入力します。 これで、Nginxが正しく起動されていることが分かりました。 … Read more

VueでPiniaを使ってみよう

VueではState Management SystemのVuexが公式のプラグインとして紹介されてきました。しかし、最新のVue3ではPiniaを使うようにとVue生みの親のEvan Youさんもお勧めしています。

では、State Management(状態管理)って何でしょうか?

State Management(状態管理)

State Managementとはいわばストレージ/ストア(倉庫)のことです。アプリケーションでストアを作っておいてそこにデータを保管できるようになります。

例えばユーザーがログインしたときのトークン、APIでフェッチしたデータ、アプリケーションの状態(例:フォームが提出したとかの状態)があげられます。

PiniaのAPIの使い方

PiniaはVue2でもVue3でも使う事ができます。また、Options API(一般的に初心者向け)でもCompotion APIの書き方でもどちらでも対応しています。私の個人的な意見ではVue3でComspostion APIで書く方法が一番良いと思います。

なぜPiniaなのか

Piniaを使う事でこの状態管理システム(Store Library)を各コンポーネントやページのどこでも使う事ができます。

もちろん、同じことが export const state = reactive({}) でもできますよね。

しかし、このやり方だとセキュリティに脆弱性があり、何を管理しているのか見られてしまう可能性があります。

この他にもデベロッパー用のツールがあったり、サーバー側でもレンダーにも対応することができるなど色々メリットがあります。

Piniaをインストール

npmかyarnのコマンドでインストールしましょう。

yarn add pinia
# or with npm
npm install pinia

※NuxtJSの場合はこちらから

インストールが完了したらmain.jsにPiniaを追加します。

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const pinia = createPinia()
const app = createApp(App)

app.use(pinia)
app.mount('#app')

Piniaのファイルを作成しよう

ではPiniaが追加できたらJSファイルでストアしたいデータを保管できる場所を作っていきましょう。

慣習的にsrcディレクトリの直下にstoreというフォルダを作成してそこにJavaScriptファイルで下記のコードを作るのが一般的になります。

import { defineStore } from 'pinia'

export const useCounterStore = defineStore({
  id: 'counter',
  state: () => ({
    counter: 0
  }),
  getters: {
    doubleCount: (state) => state.counter * 2
  },
  actions: {
    increment() {
      this.counter++
    }
  }
})
  • stateは保管するデータの初期値をリターンするファンクションです。(dataと同じ概念)
  • getters は stateを使ってデータをモディファイ(変更)したいときに使うファンクションです。(copmputedと同じ概念)
  • actionsはasyncにできるファンクションのことです。(methodと同じ概念)

<script setup>的なPiniaの使い方

他のサイトでは上記のやり方でPiniaを使っていますが、今年からVueで使えるようになった<script setup>を使ったやり方に合わせてPiniaも書きたい人は下のやり方をお勧めします。

import { defineStore } from 'pinia'
import { ref } from 'vue';
import EventService from "@/plugins/EventService";

export const useMemberStore = defineStore('member', ()=> {

  const data = ref(null)

  const getData = () => {
    EventService.getMember()
      .then((response) => {
        data.value = response.data;
      })
      .catch((error) => {
        console.log("data:" + error);
      });
  }

  return {
    data,
    getData
  }
})

上のコードを見ても分かるようにgetterとかactionsとかの概念はなく普通のJavaScriptのコードで<script setup>と同じようにVanilla JavaScriptに近い状態で書くこともできます。

個人的にはこちらの方が書きやすいと思ったので是非試してみてください。

ではこれをコンポーネントから読み込めるようにしましょう。

<script setup>

import { useOfficeStore } from "@/stores/members/office";

const officePinia = useOfficeStore();

const officeData = officePinia.data
</script>

このようにどのコンポーネントからでもStoreにアクセスでき、グローバルにデータを管理することで後から見やすくなりますね。

Django RESTクイックスタート

今日はシンプルなAPIを作成し、アドミンユーザーがブラウザから実際にAPIを見れるようにするところまで紹介したいと思います。

始める前に。。。Django REST APIはDjangoの基礎を理解していることを前提に学ぶことをお勧めします。

プロジェクトのセットアップ

 tutorialという名前のプロジェクトを作成し、 quickstartという名前でアプリを作成します。

# Create the project directory
mkdir tutorial
cd tutorial

# Create a virtual environment to isolate our package dependencies locally
python3 -m venv env
source env/bin/activate  # On Windows use `env\Scripts\activate`

# Install Django and Django REST framework into the virtual environment
pip install django
pip install djangorestframework

# Set up a new project with a single application
django-admin startproject tutorial .  # Note the trailing '.' character
cd tutorial
django-admin startapp quickstart
cd ..

プロジェクトのファイル構成はこんな感じになります。

$ pwd
<some path>/tutorial
$ find .
.
./manage.py
./tutorial
./tutorial/__init__.py
./tutorial/quickstart
./tutorial/quickstart/__init__.py
./tutorial/quickstart/admin.py
./tutorial/quickstart/apps.py
./tutorial/quickstart/migrations
./tutorial/quickstart/migrations/__init__.py
./tutorial/quickstart/models.py
./tutorial/quickstart/tests.py
./tutorial/quickstart/views.py
./tutorial/asgi.py
./tutorial/settings.py
./tutorial/urls.py
./tutorial/wsgi.py

ではデータベースを更新しましょう。

python manage.py migrate

次にDjango側のアドミンを作成します。例として、名前は admin でパスワードはpassword123にしましょう。このユーザーを後からAuthenticate(認証)で使います。

python manage.py createsuperuser --email admin@example.com --username admin

これで初期の設定はOKです。では早速ロジックを作るべく、コーディングにとりかかりましょう。

Serializers(シリアル化)

まずは、Serializersの設定をおこないます。慣習としてserializers.pyというファイル名を使うようにしましょう。では、 tutorial/quickstart/serializers.pyのファイルを作成し、データベースのデータをシリアル化させる役目をここで指示します。

from django.contrib.auth.models import User, Group
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ['url', 'username', 'email', 'groups']


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ['url', 'name']

今回は例としてHyperlinkedModelSerializerを使用しています。これはModelSerializerに似ているものです。違いは、primary keyがModelSerializerになるのですが、HyperlinkedModelSerializerはurlがpライマリーキーフィールドとして設定されます。ハイパーリンクはRESTfulのデザインとして良い慣習とされているので覚えておきましょう。

Views

Viewsでは、ユーザーからリクエストがあった際にどのような動きをさせるか指示させるファイルでしたね。通常のDjangoならHTMLのテンプレートを返したりしますが、今回はAPIを返すように指示します。

では、次の tutorial/quickstart/views.pyを開きコーディングしましょう。

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

ここでViewSetsの登場です。ViewSetsはCRUDのすべてのリクエストに対応できるスーパーセットです。これで、いちいちDELETEのリクエストやPUTのリクエストがあった動きを毎回書く必要がなくなりました。

もちろん、何か特別な動きをさせたいときはこれを上書きすることもできます。

今はこのロジックを使ってクリーンなコードのままにしておきます。

URLs

では次の tutorial/urls.pyからAPIのエンドポイントとなるURI(URL)を設定していきます。

from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

ここで覚えておきたいのが、ViewSetsはひとつのURLでCRUDのすべてのリクエストを受け取ることができることです。

なので、ここでは単純に先ほど作成したViewSetsと登録するだけでOKです。

繰り返しになりますが、単純にGETリクエストだけを受け付けたい場合は普通のクラスベースのViewを設定することでできます。

最後に、Djangoでついてくるログインとログアウトのロジックを追加することができることを紹介します。例えば顧客情報などの重要な情報は認証されたユーザーしかアクセスできないようにしたいですよね。

他にもいろいろなやり方でAPIを守る方法があるのでこれから学んでいきましょう。

Pagination(ページ)

ページネーションでは、1つのリクエストに対して返すデータの数を制限することができます。

これは tutorial/settings.pyで設定することができます。

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

Settings

次に、'rest_framework' をINSTALLED_APPSに追加してDjango側でライブライが追加されたことを登録してあげます。このセッティングのファイルはtutorial/settings.pyになります。

INSTALLED_APPS = [
    ...
    'rest_framework',
]

いいですね。


APIをテストする

では早速テストサーバーを起動してAPIを確認してみましょう。

python manage.py runserver

コマンドラインやcurlのようなツールを使ってAPIをテストすることもできます。

bash: curl -H 'Accept: application/json; indent=4' -u admin:password123 http://127.0.0.1:8000/users/
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        },
    ]
}

もしくはhttpieでもこのようにテストできます。

bash: http -a admin:password123 http://127.0.0.1:8000/users/

HTTP/1.1 200 OK
...
{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "email": "admin@example.com",
            "groups": [],
            "url": "http://localhost:8000/users/1/",
            "username": "paul"
        },
    ]
}

一番手っ取り早いのがDjangoのブラウザで確認することですね。URL http://127.0.0.1:8000/users/

Quick start image

もし、ブラウザからAPIを確認したい場合はDjangoアプリケーションにログインしていることを忘れずに確認してください。

では、これでDjango REST Frameworkのクイックスタートの説明を終了します。

VueRouterでログインしていないユーザーをログイン画面に誘導する方法

準備するもの

・Vue3

・Vue-Router

イントロ

今日はVue3でログインしていないユーザーをログイン画面に飛ばす方法を紹介します。

この方法以外にもこの目的を達成できる方法が色々ありますがVue-Routerを使ったやり肩が簡単だと思ったので参考にしてみてください。

ユーザーを判断するシステムを作る

Vueアプリにアクセスしたユーザーを判断するシステムがないことにはユーザを振り分けることができませんね。

今回は、ログインしていないユーザーをどうやって判断するかを紹介します。

前回紹介した記事でトークン認証を使ったログインの仕方を紹介しました。

では、これを使って、トークンのないユーザーをはじき出しましょう。

localStrageについて

今回は単純にブラウザのローカルストレージにデータを保管していますが、もし複雑なデータをあるかうようでしたらVuexというState Managementシステムでも同じことができます。

Vue Routerについて

Vue-RouterはVueのライブラリでURLのルーティング、もしくはページのコンポーネントを担当するメカニズムの事です。

Metaについて

このコードを見て分かるようにそれぞれのルートにmetaを設定することができます。

今回は一番ふさわしいrequireAutrhというキーで名前を付けましたが、adminOnlyでも、firstTimeでも何でも良いです。

で、このキーに対してtrueの値を入れてあげます。

後からこのrequireAuthがtureのルーティングに対して更に条件を足していきます。

const routes = [

  {

    path: "/",

    name: "home",

    component: HomeView,

    meta: { requiresAuth: true },

  },

  {

    path: "/login",

    name: "login",

    component: LoginView,

  },

];

beforeEachでルーティングに制限をかける

VueRouterの公式のドキュメンテーションにもありますが、このmetaに対して条件を足す場合には下記のようにコードを書いていくことになります。

パラメータではto とfromが使えますが今回はtoだけを使います。つまりは行き先だけを指定して、どこのページから来ているかのfromは使わないという事ですね。

to.meta.requiresAuthでさっきのrequireAuthがtrueであることと、 localStorage.getItemのtokenがnull、つまり、NoValueで値がない場合にどうするか指示します。

今回はバックエンドのアプリからログインのトークンをもらっていない場合はloginのページに誘導することにしています。

router.beforeEach((to) => {

  if (to.meta.requiresAuth && localStorage.getItem("token") == null) {

    return { name: "login" };

  }

});

では、今日はこれくらいで。