Djangoを使用するにあたって

# Djangoを使用するにあたって
各機能を利用方法を整理。

## URLディスパッチャ
アプリケーションの振り分けや、画面遷移に必要な設定を記述。

### URL設定を行うファイル指定
設定ファイルにて指定。

```py:example
ROOT_URLCONF = '<使用したいファイル>'
```

### エラーハンドリング
ハンドリング機能が備わっている。
アクセスされたURLが、どこにも存在しない場合には、handler404変数に設定されているビュー関数を介して、404.htmlテンプレートを表示する仕組みになっている。
これは、DEBUGがFalseの場合に適用される。

### urlファイルの配置
urlファイルは、肥大化を防ぐためにも、アプリケーションごとに用意するのが好ましい。

## View
使用するにあたっての知識。

### django.shortcuts
様々な方法で、レスポンスを作成する関数が揃っているので、活用する。

### TemplateView
ヘルプ、利用規約等の、静的なページを表示するのに活用するのが適切。
最低限の返り値を付与することが出来る。
その際には、get_context_data()を利用すると良い。

簡単なものであれば、URLconf内に既述すると良い。

```py:example（簡易型
urlpatterns = [
	path(r'^$',Example.as_view(template_name='example.html'),name='index'),
]
```
```py:example（動的型
class Example(TemplateView):
    def get_context_data(self, **kwargs):
        context = super(Example, self).get_context_data(**kwargs)
        context[str] = 'hello'
        return context
example = Example.as_view()
```

### RedirectView
リダイレクトに利用する。
class変数にを利用することで、リダイレクト先を指定することが出来る。

```py:example
class Example(TemplateView):
    url = 'example/page/'
example = Example.as_view()
```

URLcnfに直接各方法もある、

```py:example
urlpatterns=[
	path(r'^$',RedirectView.as_view(url='/accounts/login/'),name='index'),
]
```

[★](https://ccbv.co.uk/projects/Django/2.0/)

## ログイン処理
username、passwordを利用するログイン方式は以下を利用することが出来る。

### 基本的な実装方法
以下を利用する事が出来る。

```py:example
from django.contrib.auth import authenticate
```

session管理には以下を利用すると良い。
そうする事で、以下が行われる

- session id をキーにしたユーザー情報が生成される
- Userオブジェクトに対するレコードの最新更新日時が更新される

```py:example
from django.contrib.auth import login
```

ログイン後は、CookieからセッションIDを取り出し、sessionを利用する事が出来る。
その際にはuser属性を利用すると良い。

ログイン可否については、is_authenticated属性を利用すればいい。

適切な処理を行った後は、request.userオブジェクトにアクセスすることで、user情報を利用することが可能になる。

### ログイン、ログアウト時は
LoginView、LogoutViewを利用することで、工数が大幅に削減できる。
ログアウト時には、以下を利用。

```py:example
from django.contrib.auth import logout
```

sessionがクリアされ、userオブジェクトが更新される。



### セキュリティ
未ログインのユーザーがアクセスする際に、エラーページに遷移させることが出来る。

```py:example
from django.contrib.auth.mixins import LoginRequiredMixin
```
定義するだけで、LOGIN_URLに設定したURLにリダイレクトしてくれるので便利。
raise_exceprion = Trueを定義すれば、403エーラ画面へ譲渡することが出来る。

## モデル
以下のクラスを利用する。

```py:example
from django.db.models import Model
```
### 基本的な扱い方
使用する際には以下を利用。
抽象クラスを利用する以外は、１つのテーブルに対して、モデルクラスひとつで対応する。

Class定義時に、db_tableを定義していない場合にはデフォルトのテーブル定義が行われる。

- <アプリ名>_<クラス名のスネークケース>

- 主キーは自動生成されるため、定義の必要はない
- 主キーはレコード登録に度に自動採番
- 複合キーは主キーに出来ない

### リレーション
リレーションを活用するテーブルを構築する際には、on_delete属性が必須と成っている。
以下の機能が備わっているので、有効活用する。
- レコード削除
- 削除を行わない
- NULLのセット
- デフォルト値のセット

### Modelの拡張
Modelの拡張を行う際には、以下のClassを拡張するのが一般的。

- AbstractBaseUser
  - ほぼ別なClassを作りたい場合に使用
- AbstractUser
  - 多少手を加える場合に使用 
- OneToOneField

AbstractBaseUser,AbstractUser を利用する場合には、設定が必要となる。

```py:setting.py
AUTH_USER_MODEL = '<アプリ名>.ExampleUser'
```

```py:model.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class ExampleUser(AbstractUser):
    class Meta:
        db_table = 'example_user'
    ...

```

カスタムユーザーを使用する際には、以下関数を利用する。

```py:example
from django.contrib.auth import get_user_model
get_user_model()
```


すでに可動済みのUserモデルを拡張したい場合には、OneToOneFieldを利用すると良い。
Userモデルに手を加えてしまうと、スキーマが変わってしまい、必要以上に影響を与えてしまうので危険。

## Templateを利用するにあたって
基本利用以外で気をつけること。

###url逆引き
ハードコーディングを避けるために、パターン名を既述する方法がある。

```py:example
{% url 'index' %}
{% url 'example:login' %}
{% url 'index' user.id %}
{% url 'index' user_id = user.id %}
```
### エスケープ処理
積極的に、{% autoescape %} を利用する。
引数に、on off の設定ができ、有効、無効を切り替えることが出来る。

```py:example
# 無効
{% autoescape off %}
```

## Form
機能使用は必須ではないが、以下を覚えていると、工数削減にとても役に立つ。
is_valid()実行時の、内部で動くバリデーションは複数存在し、その実行順序は決まっている。

### Form前提知識
- フィールド定義のバリデーション
 1. to_python()
 2. validate()
- フォーム定義のバリデーション
 3. run_validation()
 4. clean_<フィールド名>()
 5. clean()

to_python()、validate()は、自作したclassを使用する場合に使用するため、基本的には気にしなくて良い。
run_validation()は、フィールドのvalidation属性に定義している場合に実行されるが、django.forms.fields.Fieldのサブクラスを適切に使用している鍵に、気にしなくて良い。

validationが行われ、正常終了シた際には、辞書型のcleand_date変数に、検証済みのデータとして保持される。
不正常終了時には、エラーメッセージがlist型の変数としてほじされる。

is_valid()の処理が行われた時のみ、clead_dateに値が保持されるため、処理前にアクセスすると例外が発生するので注意が必要。

### Viewでの使用方法
Form機能を使用しない場合。
ここから、validationを自作する必要がある。

```py:view.py
example = request.POST.get('example')
```
Formを使用する場合。
requestデータを、FormのClassを呼び出すときに引数として渡せば、Djangoの機能を利用したValidationが可能となる。

```py:view.py
form = ExampleForm(request.POST)
is_valid = form.is_valid()
```

結果はbool型で返却されるため、結果に応じてTemplateへ渡してあげればいい。
その際には、エラーの内容が、Formクラス呼び出時の結果として返却されている。
上記だとformに格納されているので、Templateに渡してあげれば画面へ反映することが出来る。

### Templateへの反映
render等で渡された値をレンダリングするだけでいい。

```py:template.html
{{ <渡された変数名> }}
```

出力順は、Formでの定義順になる。
もし、変えたい場合にはFormクラスにField＿orderへ定義すればいい。

```py:form.py
class ExampleForm(forms.Form):
    field_order = ['pass', 'user']
```

### エラーメッセージ
validationエーラ結果のメッセージは、fieldのerrorsに追加される。
clean()メソッドによる結果は、non_field_errorsに追加されている。

### CSRF対策
POSTリクエスト時に、CSRFmiddlewaretokenエラーが発生する場合がある。
tokenの記述が正しく行われていないために発生するエラーなので、Templateのform内部に{% crsf_token %}を既述すると良い。
CsrfViewMiddewareの設定を無効化していると発生しないエラーだけど、セキュリティ上、必須レベルなしくみなので、忘れないようにする。

### ModelForm
追記中