tail -f /dev/null

If you haven't had any obstacles lately, you're not challenging. be the worst.

Djangoのviewをレンダリングしてみたい

Djangoのおべんきょう。

f:id:hrt0kmt:20190613211613p:plain
startup page.

Install

pip install Django

Environment

django-admin --version
2.2.2

Feature

Djangoの特徴は以下の通り。

  • 機能拡張が豊富。
    • 以下、標準装備。
      • user auth
      • 管理サイト機能
      • cache機能
      • 多言語翻訳機能
  • migrationが容易。
  • MTV framework。
    • model, template, viewで構成されるframework
    • ※実はMVCのVをtemplate, viewに分割しているだけでMVCと変わらない。

Basic component

要素 概要
view model, form, templateと連携してresponseを作成。
URLconf URLパターンとviewのmapping情報。
URL dispatcher(処理振り分け) - URLconfに登録されたrequest URLにマッチするviewを返す。
- URLconf -> URL dispatcher-> request uri -> view function を正引きする。
model model classとDBのtable定義を紐付ける。
template model object, form object等の変数をrenderingして動的にHTMLを生成する。
form viewの入力値をobjectに変換しvalidationを実行する。
middle ware requestの前処理、responseの後処理を行いブラウザへ返す。

Project component

要素 概要
project 一番大きな概念。
application 機能毎の分割された、moduleを内部から呼び出せるname space(名前の衝突を防ぐ為の集合の分割概念)を備えたPython package(directory)。
command utility - django-admin.py : projectの雛形を作成する
- manage.py :管理コマンドが使える。

Create project

サッとproject作ってローカルにサーバ立ち上げるのを試すだけならこちらを参照すれば出来る。

virtualenvのactivate

pip install virtualenv
pyenv virtualenv 3.7.0 django
pip install django
pip install cookiecutter

projectの作成

mkdir xxx
cd xxx

# create project
django-admin.py startproject config .
tree -aRQt -I 'bin|lib|include|.gitignore' xxx
"xxx"
├── "config"
│   ├── "__init__.py"
│   ├── "settings.py"
│   ├── "urls.py" # URLconf
│   └── "wsgi.py" # WSGI interface対応のweb serverからDjango siteを起動する際のendpoint
└── "manage.py"

Create app

# create application
python manage.py startapp accounts
ls accounts
__init__.py admin.py    apps.py     migrations  models.py   tests.py    views.py

Project作成のbest practice

cookiecutterでproject templateを生成するのがbest practiceとのこと。
optionは、Project Generation Optionsを参照。

cookiecutter https://github.com/pydanny/cookiecutter-django

project_name [My Awesome Project]: xxx
project_slug [xxx]: xxx
description [Behold My Awesome Project!]: your xxx.
author_name [Daniel Roy Greenfeld]: xxx
domain_name [example.com]: localhost
email [xxx@example.com]: xxx
version [0.1.0]: 0.1.0
Select open_source_license:
1 - MIT
2 - BSD
3 - GPLv3
4 - Apache Software License 2.0
5 - Not open source
Choose from 1, 2, 3, 4, 5 (1, 2, 3, 4, 5) [1]: 2
timezone [UTC]: Asia/Tokyo
windows [n]: n
use_pycharm [n]: n
use_docker [n]: n
Select postgresql_version:
1 - 10.5
2 - 10.4
3 - 10.3
4 - 10.2
5 - 10.1
6 - 9.6
7 - 9.5
8 - 9.4
9 - 9.3
Choose from 1, 2, 3, 4, 5, 6, 7, 8, 9 (1, 2, 3, 4, 5, 6, 7, 8, 9) [1]: 1
Select js_task_runner:
1 - None
2 - Gulp
Choose from 1, 2 (1, 2) [1]: 2
Select cloud_provider:
1 - AWS
2 - GCE
Choose from 1, 2 (1, 2) [1]: 1
custom_bootstrap_compilation [n]: n
use_compressor [n]: n
use_celery [n]: n # 分散タスクキュー redisとかあること必要 https://github.com/pydanny/cookiecutter-django/issues/1775
use_mailhog [n]: n
use_sentry [n]: n
use_whitenoise [n]: n
use_heroku [n]: n
use_travisci [n]: n
keep_local_envs_in_vcs [y]: y
debug [n]: y

requirementsの読み込み。

pip install -r requirements/base.txt
pip install -r requirements/local.txt

databaseを作成

create database xxx;

migrate & runserver

python manage.py migrate
python manage.py runserver

f:id:hrt0kmt:20190701114132p:plain
初期画面

superuserの作成

python manage.py createsuperuser

ディレクトリ階層

tree -daRQt -L 3 -I 'bin|lib|include|.gitignore'
.
├── "config"
│   └── "settings"
├── "locale"
├── "requirements"
├── ".envs"
│   ├── ".local"
│   └── ".production"
├── "docs"
├── "xxx"
│   ├── "contrib"
│   │   └── "sites"
│   ├── "static"
│   │   ├── "css"
│   │   ├── "fonts"
│   │   ├── "images"
│   │   ├── "js"
│   │   └── "sass"
│   ├── "taskapp"
│   ├── "templates"
│   │   ├── "account"
│   │   ├── "pages"
│   │   └── "users"
│   └── "users"
│       ├── "migrations"
│       └── "tests"
└── "utility"

URL dispatcher

URL dispatcherurls.py における URLconf と呼ばれるURLに紐付くview functionのlistに基づき、request URLに対応するview functionを呼び出す(正引き)。

find . -name 'urls.py'
./config/urls.py
./xxx/users/urls.py

path converter記法

  • path converter (django.urls.path function) を利用してURLパターンを記述する。
  • <> 内がcaptureされview function呼び出しの引数として利用される。

application毎にurls.pyの配置を替える

  • config/urls.pydjango.conf.urls.include 関数を利用してURL ruleの記載が1つのファイルに集中して肥大化しないようにする。
    • Apacheでconfをincludeするのと同じだな
  • users/ 配下をincludeファイルの方で定義する場合は以下の通り。
    • ディレクトリ階層は上方の ディレクトリ階層 を参照のこと。
  • app_name(namespace)は必ず設定する。
urlpatterns = [
    path("users/", include("xxx.users.urls", namespace="users")),
    path("users/", include("xxx.urls", name="users")),
]

View

流れは以下の通り。

  1. URL dispatcherからview functionを呼び出す
  2. django.http.request.HttpRequest objectを受け取る
  3. django.http.response.HttpResponse objectを返却する
  4. viewでrequestされたobjectのデータを型変換
  5. validation
  6. 変数に格納
  7. templateやredirect先へ変数の内容をHTMLにrenderingし、viewからresponse objectとして送信される

view function

  • django.views.generic.base.View
    • viewはfunctionベースとclass(で設計してview functionへ変換する)ベースがある。
    • classベースの方が豊富なclassが提供され、generic viewを利用することにより柔軟に書ける。
      • generic view
        • django.views.generic.base.View, django.views.generic.base.TemplateView, django.views.generic.base.RedirectView
    • django.shortcut packageは様々なresponseを返却する関数が揃っている。
      • 例えば django.shortcuts.render() はHTTP response objectを生成してくれる。
    • django.http.response.Http404, django.core.exceptions.PermissionDenied で例外をraise出来る。
    • redirectは return redirect(reverse('admin:index')) のような形で出来る。
from django.contrib.auth import login as auth_login
# rendering template and redirect
from django.shortcuts import render, redirect
from django.urls import reverse
from django.views.generic import View

class Xxx(View):
    def get(self, request, *args, **kwargs):
        context = {
            'form': LoginFrom(),
        }
        return render(request, 'admin/xxx.html', context)

# as_view(): classベースのviewをview function化しURL dispatcherと他のviewから呼び出せるようになる
x = Xxx.as_view()
  • django.views.generic.base.TemplateView
    • generic viewにはtemplateに渡すHTML contextをoverride出来るvariablesやmethodが存在する。
  • django.views.generic.base.RedirectView
    • class variablesの代替としてURLconfのpattern名を利用出来るvariables pattern_name
    • redirect URLを動的に生成する get_redirect_url methodをoverrideすることが出来る。

override出来るvariables, method

  • template_name
    • 利用template
  • model
    • 利用するmodel class
  • querysert
    • object listを取得
  • get_queryset
    • object listを動的に変更
  • context_object_name
    • object listを格納
  • get_context_data
    • templateに渡すcontextを動的に変更
  • get_template_names
    • templateを動的に変更