pythonでのWebアプリケーション開発メモ

#はじめに
pythonでスクレイピングを学んだ後に、取得したデータを利用したWebアプリケーションを作りたくなったので、実現方法を調べたメモです。

##どのフレームワークがよいか？
Djangoというフレームワークがおススメとのこと。

- 参考記事：[PythonでWebアプリケーションを開発！人気のフレームワークも大紹介](https://www.sejuku.net/blog/87802)

Djangoの詳細はこちら。

- [Django ドキュメント](https://docs.djangoproject.com/ja/3.1/contents/)
- [Github](https://github.com/django/django)

##Djangoのインストール方法
以下を参照した
[【Django入門】あなたのパソコンにDjangoをインストール！](https://www.sejuku.net/blog/28235)

`$ pip install django`を実行しようとしたところ、pip自体のバージョンが古いと言われ、アップデートする必要があった...

- 参考記事：[Python Tips：pip そのものをアップデートしたい](https://www.lifewithpython.com/2015/07/pip-upgrade-itself.html)


Git Bashで`$ python`でpython shellを起動しなかった。
なんか仕様らしい...
pythonはGit Bashで扱わない方がよさそう（大人しくコマンドプロンプトで実行）

- 参考記事：[Git for WindowsでPythonがうまく動かない場合の対処法](https://qiita.com/icoxfog417/items/33e6b1f3dd9358923e21)

##プロジェクトとアプリケーションの作成
- 参考記事：[【Django入門】Djangoアプリの設計哲学！MTVモデルをmodelsを通して学ぼう！](https://www.sejuku.net/blog/27387)

プロジェクト作成のコマンドは以下

```
django-admin startproject mySite
```
テンプレート作成のコマンドは以下

```
python manage.py startapp myapp
```

modelという機能を利用することで、DBを直接触らなくてもデータベースをいじれるらしい（３階層構造のアーキテクチャで作りたかったので、DBを簡単に操作できるのはありがたい）

modelを編集する際の手順としては以下の通り。

1. modelを書く
1. `python manage.py makemigrations アプリ名`の実行
1. `python manage.py migrate`の実行

##modelの使い方
- 参考記事：[Django 3.0 のモデルフィールドリファレンス一覧まとめ](https://qiita.com/KeAt/items/55fdedc8cac7c6852043)

##templateの利用方法
 - 参考記事：[【Django入門】templateとHTMLを使ってWebページを表示しよう](https://www.sejuku.net/blog/26407)

まず、`settings.py`ファイル内の`TEMPLATES`にある`'DIRS'`以下の記述を追記する。

```
os.path.join(BASE_DIR, 'templates'),
```
これで「templatesというディレクトリにtemplateファイルを入れていくこと」を宣言している（らしい）。

その後templatesディレクトリを作った後にテンプレート表示処理を作る流れとしては

- view関数の定義
- URLとview関数の紐づけ（プロジェクトとアプリケーションそれぞfれで）

という感じ。

紐づけ終わったら

```
python manage.py runserver
```
のコマンドを実行すると、ローカルホストでサーバーを起動してテンプレートが表示されるかを確認出来る。

djangoのtemplateには色々な便利機能があるので、使ってみたいなと思った。
詳しくは[公式ドキュメント](https://docs.djangoproject.com/ja/3.1/topics/templates/)を参照のこと。

###{% csrf_token %}によるCSRF対策ついて
- 参考記事：[【Django】 csrf_tokenの仕組みとCSRF無効化・画面カスタマイズする方法](https://djangobrothers.com/blogs/django_csrf/)

DjangoではデフォルトでCSRFの検証を行ってくれる。
CSRFとその対策に関する詳細は以下を参照のこと。

- [「クロスサイトリクエストフォージェリ（CSRF）」とは？](https://www.trendmicro.com/ja_jp/security-intelligence/research-reports/threat-solution/csrf.html) 
- [CSRF(クロスサイトリクエストフォージェリ)の意味と対策方法](https://djangobrothers.com/blogs/csrf/)


##Webページに入力したデータを元に、スクレイピングを実行し、表示するまでの一連の流れ
参考記事：[python:WEBアプリを作ろう（djangoでスクレイピング）](https://note.com/tamurasann/n/nc19a299e11bb#l9c8r)

`views.py`ファイルの中で色々と記述していくことになる

###viewという概念
viewはMTV(Model, Template, View)という設計思想を採用しているdjangoにおいて、「ブラウザからのリクエストを元に、表示させるページ/データを取得して、レスポンスを生成する」機能を担っている

- 参考記事：[MTVを理解しよう](https://djangobrothers.com/tutorials/memo_app/mtv/)

そしてdjangoにはユースケースに応じて適切なデフォルト値を設定しておいてくれる、「汎用ビュー」と呼ばれる機能がある

- 参考記事：[Djangoにおけるクラスベース汎用ビューの入門と使い方サンプル](https://qiita.com/dai-takahashi/items/7d0187485cad4418c073)

汎用ビューの種類の使い分け方法は以下を参照

- 参考記事：
    - [Djangoにおけるクラスベース汎用ビューの入門と使い方サンプル](https://qiita.com/dai-takahashi/items/7d0187485cad4418c073)
    - [Djangoの 汎用クラスビューをまとめて、実装について言及する](https://qiita.com/renjikari/items/af3e8958d2653e6f8d46)

今回はWebページが入力したデータを元にスクレイピングを走らせたいので、formを使える`CreateView`を利用する。

###reverse/reverse_lazy関数について
`CreateView`の`success_url`変数（作成成功時に遷移するページのURL）を指定する時は、`reverse_lazy`と呼ばれる関数を利用する。

`reverse`や`reverse_lazy`という関数は「名前を指定してurlを呼び出す」際に利用される。

- 参考記事：[reverseの使い方について分かりやすく解説【具体的なコード付き】](https://codor.co.jp/django/how-to-use-render)

具体的に言うと、reverse('home')とした場合、urlpatternsでname='home'と指定したurlを呼び出す。

`reverse`と`reverse_lazy`が何が違うかと言うと、「URLConf(=urls.py)を読み込む前に`reverse`関数を利用する場合は、`reverse_lazy`を利用する」みたい。

- 参考記事：[[Django] success_urlとget_success_urlおよびreverseとreverse_lazyの使い分け](https://btj0.com/blog/django/success_url-get_success_url-reverse-reverse_lazy/)

クラスの中で利用する場合は「URLConf(=urls.py)を読み込む前」に相当するらしいので、`revese_lazy`を利用する。

遅延評価(lazy evaluate)を正しく理解するにはpythonにおいて何がどういうタイミングで評価されるかを理解する必要があるみたいだが、正直よく分からない...

- 参考記事：[Difference between reverse() and reverse_lazy() in Django](https://stackoverflow.com/questions/48669514/difference-between-reverse-and-reverse-lazy-in-django)

###pythonにおけるリストと要素追加方法
- 参考記事：
    - [【Python】appendの使い方を理解しよう！役割や実践方法を徹底解説！](https://www.tech-teacher.jp/blog/python-append/)
    - [既存のlistに複数の値を一度に追加したいときは「+=」または「extend()」を使うと1行で書ける](https://qiita.com/tag1216/items/416314cc75a099ad6149)

`append()`関数を利用することで、既存のリストに単一の要素を追加できる。
`extend()`関数を利用することで、既存のリストに複数の要素を追加できる。

※<b>`append` の引数にリストを入れると元のリストの中にそのままネストされてしまうことに注意！</b>
extendを使えばそのままリスト内の要素として追加させる（ややこしい...）

###render関数について
参考記事：

- [Python Django チュートリアル(3)](https://qiita.com/maisuto/items/eece9d880d94fd241a0d#template%E3%81%AE%E5%88%A9%E7%94%A8)
- [公式ドキュメント](https://docs.djangoproject.com/en/3.1/topics/http/shortcuts/#render)

requestとテンプレートパスを渡すとそのテンプレートを使用したレンダリング結果をHttpResponseとして返してくれる関数。
第３引数に辞書型の値を渡すことで、templateに値を渡すことが出来る。

<b>⇒これで`append`関数で辞書型のリストに突っ込んだ要素（スクレピングで取得したもの）をtemplateに渡し、HTML内の要素としてはめ込める</b>

###djangoにおけるmodelについて
- 参考：[公式ドキュメント](https://docs.djangoproject.com/ja/3.1/topics/db/models/)

modelクラスに対してはデフォルトで１つの`Manager`が追加されている。

- 機能：DB操作のためのインターフェイスを提供している
- 名前：`objects`（なんでmanagerではないのだろうか...？）

モデルマネージャーは色々なメソッドを持っている。

- `.objects.all()`：DB内の全ての要素を返却する
- `.objects.filter()`：条件を指定して返却する

注意：モデルマネージャーが持っているメソッドを呼び出すには`.objects`の記述が必須
参考：[【初心者向け】Djangoのモデル操作でobjectsが必要な場合・不要な場合を理解する](https://qiita.com/shonansurvivors/items/12b087cf5ab591273c8c)

##pythonにおける条件文の書き方
- 参考記事：[［Python入門］if文による条件分岐](https://www.atmarkit.co.jp/ait/articles/1905/07/news019.html)

基本的なことだが重要

##pythonにおける比較演算子
-　参考記事：[比較演算子の使い方](https://www.javadrive.jp/python/if/index4.html)

「等しい」が`=`ではなく`==`であることを忘れがち

##pythonにおけるreturn文
- 参考記事：[戻り値をマスターしよう！Pythonのreturn文の使い方を簡単解説](https://www.tech-teacher.jp/blog/python-return/#rink_4)

リストを返却したければ、`return [aaa,bbb]`のような形で書けばよい。

##pythonにおける関数の使い方
- 参考記事：[python 関数の基本が初心者でもわかる！引数や戻り値も理解できる！](https://udemy.benesse.co.jp/development/python-work/python-function.html)

基本的だけど重要な話。

##pythonにおけるデータの型
- 参考記事：
    - [[Python]リスト、タプル、辞書、集合の違い](https://qiita.com/taro-ari/items/9f54536fe3c623813db1)
    - [［Python入門］リストの基本 (1/4)](https://www.atmarkit.co.jp/ait/articles/1905/31/news015.html)

色々あるから、使いながら覚えていこう。

###辞書型
- 参考記事：[Pythonで辞書に要素を追加、辞書同士を連結（結合](https://note.nkmk.me/python-dict-add-update/)

辞書に新しい要素を追加する場合は、`辞書オブジェクト[キー] = 値`で実現出来る