[大学生ウケ抜群] React(Axios)とPython(Django)で簡単Webアプリ開発！！

#忙しい人のために！
1. mkdir プロジェクト名&&cd プロジェクト名&&crate react-app (--template typescript)でフロントのベースを作成！
1. rootでディレクトリでdjango-admin startproject+django-admin startappでバックのベースを作成
1. フロントにAxiosをインストールし、App.js or App.tsxにポート8000番にGETリクエストを送るようなボタンでも作る（AxiosでGETリクエストを送ることさえできればなんでも良い）
1. バック側のstartappで指定したディレクトリのviews.pyとurls.py(新しく作る)にてとレスポンスとリクエストのurl指定を作成。
1. startprojectで指定したディレクトリのurls.pyでstartapp側のディレクトリのurls.pyをincludeする
1. startprojectで指定したディレクトリのsettings.pyにてインストールapp、middlewareとcorsの対策を記述する。
1. rootディレクトリ上からcd front&&yarn start => 3000番が立ち上がる
1. rootディレクトリ上からcd back&& python manage.py migrate(初回だけ)&&python manage.py runserver => 8000番にサーバーが立ち上がる
1. この状態で3000番のビューのPush!!ボタンをクリックしてYay!!とでたら成功です!


#ちゃんとみてくれる方へ！
ありがとうございます！

今回の記事のざっくりとした仕組み図です！
![スクリーンショット 2021-08-22 14.07.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699416/0f2f5e6a-8d70-e818-9908-cb264a10fcd1.png)



#作成の動機
チーム開発でフロントエンドをReact,バックエンドをPythonにすることが決まりました。

バックエンドをPythonで書くときのフレームワークはFlaskしか触ったことがなく、これを機にDjangoを勉強してみようと思い、作った試作アプリの過程をこの記事に吐いてます！

#プロジェクトディレクトリ図
>
root/
   ┣ back
   ┃   ┣ back(rootディレクトリでのdjango-admin startprojectで作成)
   ┃   ┣ backend(django-admin startappで作成)
   ┃   ┗ manage.py
   ┃
   ┣ front
   ┃   ┣ public
   ┃   ┗ src
   ┃       ┗ App.js
   ┗ READMEとか、、、
>

今回は一つのプロジェクトにbackendとfrontendのソースを入れることにしています。

#環境

#### OS
- macOS Catalina 10.15.7

#### front
- node v16.0.0


#### back
- python                            3.9.0
- Django                            3.2.6
- django-cors-headers               3.8.0
- djangorestframework               3.12.4

バックエンドの実装ではvenvを使ってDjango用の仮想環境を別途構築した方が他のプロジェクトのことも考えると良いと思います

今回は目的と外れるのでvenvでの仮想環境の構築とプロジェクトへの適用は解説しませんが、下記に参考資料を載せておきます

また、pythonをWeb開発にごりごり使いたいよーって人はvertualenvwrapperというvenvで構築した仮想環境を管理できるライブラリを使用するのもおすすめです！

1. [venv: Python 仮想環境管理](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)
1. [Virtualenvwrapperの導入](https://qiita.com/_rdtr/items/5f3a9a9e2cb5a24f284e)
1. [[環境構築] Pythonで機械学習もWeb開発もやりたいよ！！っていう素敵な欲張りさんへ](https://qiita.com/monta0315/items/747a3f135802cb32d177)

#front実装1
```
1. mkdir project名&&cd project名
# 今回はsample_appにしています

2. yarn create react-app front  
#TypeScriptを使用する場合は --template typescriptも

3. cd front&&yarn add Axios 
```

これで一旦front側に必要な環境の構築が完了しました

今回はパッケージマネージャにyarnを利用していますが、npmでも大丈夫です

後ろにAxiosについての簡単な説明を乗っけておきますので、Axiosとはなんぞやという方は見てみてください！！

#front実装2
frontディレクトリの中にあるsrcディレクトリのApp.jsを次のように変更します。

```jsx
import { useState } from "react";
import "./App.css";
import logo from "./logo.svg";
import axios from "axios";

function App() {
  const [text, setText] = useState("");

  const handleClick = () => {
    axios.get("http://127.0.0.1:8000/test").then((res) => {
      console.log(res);
      setText(res.data);
    });
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <button type="button" onClick={handleClick}>
          PUSH!!
        </button>
        <h1>{text}</h1>
      </header>
    </div>
  );
}

export default App;
```
見た目はこんな感じになります

![front見た目](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699416/86555184-41db-e161-8432-c15e19977a41.png)

##ざっくり説明
1. ボタンを配置し、そのボタンをクリックしたときにhandleClick関数が発動するようにしています
1. handleClick関数はクリックされた際にAxiosを利用して"http://127.0.0.1:8000/test" このURLにGETリクエストを送信する仕組みにしています(後に説明するバックエンドでサーバーを立ち上げた時のURL/testを記述してください！)
1. バックエンド側から返ってきたResponseの中のdataをsetTextメソッドによってボタンの下に表示するようにしています。
1. バックエンドからはYay!!という文字列をレスポンスに含めているので下記のような見た目になります。

![スクリーンショット 2021-08-22 12.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699416/64127d4f-90aa-cb20-c65c-59993e04c90d.png)

#back実装1
ルートディレクトリ（今回で言うとsample_app）に戻ってください！
今回のバックエンドの開発に必要なライブラリを入れていきます

```
pip install Django                     
pip install djangorestframework 
pip install django-cors-headers           
```
##ざっくり説明
###Django
DjangoとはPythonでバックエンドを開発する際に利用するフレームワークの一つです。

同じようなことができるフレームワークとしてFlaskがありますが、今回はDjangoを使用します
[DjangoとFlaskの違いは？PythonのWebフレームワーク2種を比較します](https://blog.pyq.jp/entry/Python_kaiketsu_210601)

###djangorestframework

djangorestframeworkはflaskと同じぐらい簡単にWebAPIサーバーを構築できるやつです！すごい！

###django-cors-headers

djnago-cors-headersを利用してバックエンドにフロントで立てたportのアクセス権を付与します
これをする理由はCORS(オリジン間共有)で怒られないためになんですが、CORSとはなんぞやという人はこれを機に勉強するといいと思います！（自分も勉強します、、、）
[なんとなく CORS がわかる...はもう終わりにする](https://qiita.com/att55/items/2154a8aad8bf1409db2b)


#back実装2
django-adminでプロジェクトとWebAPIサーバー用のアプリケーションを作成

```
1. django-admin startproject back&&cd back

2. django-admin startapp backend
```

#back実装3
- backディレクトリの中のsettings.pyをいじる

```py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
   +'rest_framework',
   +'corsheaders',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
   +'corsheaders.middleware.CorsMiddleware',
]

#これを追加
CORS_ALLOWED_ORIGINS = [
    'http://localhost:3000',
]
```
CORS_ALLOWED_ORIGINSでどのオリジン（どのURL）からのアクセスを許可するかを指定
フロントで立てたポートを指定してください（自分は3000番に立てたので上のように指定しました）

- backディレクトリの中のviews.pyとulrs.pyを設定する

###views.py
```py
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(["GET"])
def test(request):
    return Response("Yay!!", status=status.HTTP_201_CREATED)

```
testという関数にリクエストが入ってきたら"Yay!!"というレスポンスをリターンするように記述

###urls.py(無いと思うので作成してください touch urls.py)
```
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from backend import views

urlpatterns = [
    path('test', views.test),
]

urlpatterns = format_suffix_patterns(urlpatterns)
```
/testにリクエストが来たときviews.pyのtest関数にリクエストを渡すように記述

###backディレクトリのurls.pyもいじる（こっちはもともとあると思います）

```py
from django.urls import path, include

urlpatterns = [
    path('', include('backend.urls')),
]
```
プロジェクト自体にアプリケーションで指定したURLの存在を設定する

これでコーディングは終了です！！

# アプリの動かし方
rootディレクトリ上から
- cd front&&yarn start => 3000番が立ち上がる
- cd back&& python manage.py migrate(初回だけ)&&python manage.py runserver => 8000番にサーバーが立ち上がる
- この状態で3000番のビューのPush!!ボタンをクリックしてYay!!とでたら成功です!

#後書き
ここまで読んでくださった方、誠にありがとうございます！

正直、説明が簡潔では無い部分が多く、読みにくかったと思われましたよね、、、

このようなベースとなる仕組みを作成するだけでもDB周りの知識をつけるだけで自分の作りたいアプリケーションを簡単に作れると思います！！

では良い開発ライフを！！！