Quantcast
Channel: django - akiyoko blog
Viewing all 52 articles
Browse latest View live

ゼロからはじめる Django で ECサイト構築(その1:ECパッケージの選定)

$
0
0

はじめに

とあるニーズがあって、Python(ほぼ Django 一択)ベースの ECパッケージを使った ECサイトを構築しようかと、昨年の10月頃から細々と調査をしていたのですが、EC-CUBE や osCommerce、Zen Cart、Magento、WordPress + WelCart など PHPベースの ECパッケージについて書かれた記事は数多く存在するのですが、Pythonベースの ECパッケージについての記事があまり無いように思ったので、勉強がてらメモを残していきたいと思います。




 

ECサイトのタイプ

まず第一に、ECサイトには、以下に示したような構築方式および出店方式の違いがありますが、導入実績や信頼性、初期・月額費用、構築期間、カスタマイズ性、専門知識の必要性、集客・販促の必要性などの特徴を考慮しつつ、目的に合ったものを採用する必要があります。

以下の表では、構築・出店方式のタイプ別に、構築や運用の手間がかかりそうな順に並べてみました。

構築・出店方式概要代表例
フルスクラッチ型フルスクラッチで構築
無料パッケージ型オープンソースの ECパッケージをサーバに導入EC-CUBEZen CartLive Commerceなど
有料パッケージ型有料の ECパッケージをサーバに導入ecbeingコマース21など
ASP型ECサービスをレンタルえびすマートエレコマなど
インスタントEC型簡単にネットショップ開設Stores.jpBASEなど
オンラインモール型Web上の仮想商店街楽天市場、Amazon、ポンパレモールなど
C2Cモール型消費者間取引ヤフオク、メルカリLINE MALLなど






参考



私の場合は、カスタマイズ性と構築費用(ECパッケージのコストゼロ)を最優先させかったので、オープンソースの ECパッケージを利用する「無料パッケージ型」を採用することとしました。



 

ECパッケージの特徴

そもそも ECパッケージとは、ECサイト(電子商取引をするためのネットショップ)を構築するために必要な数々の機能を一つにまとめたソフトウェアを指します。


一般に、ECパッケージに求められる機能としては、

  • ショップフロント機能
    • 商品紹介
      • 商品カテゴリ別表示
      • 商品一覧
      • 商品詳細
      • 商品検索(キーワード / 価格帯)
      • 商品の並び替え(注文数 / 価格 / 新着 / ユーザー評価)
      • 最近閲覧した商品紹介
      • ユーザー評価(レビュー)
    • 商品注文
      • ショッピングカート
      • 決済手続き
        • クレジットカード決済
        • 振込決済(コンビニ / 銀行 / 郵便局)
        • 代引決済
        • 携帯キャリア決済
      • タイムセール
      • クーポン
      • ディスカウント(ボリュームディスカウント / 配送料無料)
      • ゲスト注文
      • 予約注文
      • 関連商品・レコメンド(この商品を買った人はこんな商品も買っています)
    • メンバーシップ
      • アカウント登録
      • 退会
      • パスワード変更
      • ログイン
      • ログアウト
    • マイページ
      • 注文履歴
      • 配送先登録
      • お気に入り登録(ほしい物リスト)
    • 問い合わせ
  • バックオフィス機能
    • 商品管理
      • 商品カテゴリ登録
      • 商品登録
      • タイムセール登録
      • クーポン登録
      • ディスカウント条件設定
    • 受注管理
      • 消し込み(返品処理)
    • 顧客管理
    • 問い合わせ管理
    • 売上集計
    • 販売分析
    • 各種メール送信
    • システム設定
      • システムメンテナンス
      • デザインテーマ設定
      • 多言語化

などが挙げられます。


無料パッケージにせよ有料パッケージにせよ、ECパッケージの選定においては、上記の機能がどれだけ実現できるかが一つの重要な選定基準となります。




 

ECパッケージの選定

ここで、ECパッケージを選定するために、Djangoベースの ECパッケージの中から人気のあるものをリストアップしてみます。


Djangoベースのパッケージの評価するには、Django Packages : E-Commerceを参照するのが手っ取り早いです。

Django Packages で比較

スター数の上位 4つをリストアップしてみました。
(「SATCHLESS」は最近開発が活発でなくなって来ているようなので、除外しました。)


PACKAGEDJANGO-OSCARDJANGO SHOPSALEORCARTRIDGE
DescriptionDomain-driven e-commerce for DjangoA Django based shop systemAn e-commerce storefront for Python and DjangoEcommerce for Mezzanine
CategoryFrameworkFrameworkFrameworkApp
Development StatusProduction/StableUnknownn/aBeta
Last updatedApril 3, 2016, 5:30 a.m.May 16, 2016, 9:40 a.m.May 11, 2016, 10:38 a.m.April 4, 2016, 2:54 a.m.
Version1.2rc10.9.1n/a0.11.0
Stars19971044501464
Repo Forks814438199222
Payment MethodsGateways: DataCash, PayPal, PaymentExpress. There is also an accounts extension that provides support for giftcards, loyalty schemes and customer budgets.cash-on-delivery paypal (ext), postfinance (ext) Easily extensibleAll supported by django-payments: Authorize.net, Braintree, Coinbase, Cybersource, Dotpay, Google Wallet, PayPal, Sage Pay, Sofort, StripeAuthorize.net, eGate, PayPal, Stripe, Braintree, PIN
Shipping optionsExtremely flexible. Any part of the shipping calculation can be customised to suit your domain.Flat rate, easy api for extensibilityPer-country shipping rules provided out of the box, custom options are easy to implement. Split deliveries for a single orderFlat rate provided plus hooks for implementing your own rules
Configurable Checkout StepsYes - The checkout can be easily customised to add, remove, alter or combine steps. It's not controlled by a single setting though.Saleor is meant to be forked so you can just edit the code

Django Packages : E-Commerceより抜粋。2016年5月22日時点のもの)


DJANGO-OSCAR」と「DJANGO SHOP」が二大人気となっているようですが、「DJANGO-OSCAR」のスター数・フォーク数はほぼダブルスコアになっています。

なお、CARTRIDGEのカテゴリが「App」となっていますが、このパッケージはショッピングカート機能のみを提供するもので、「Mezzanine」という CMSパッケージ向けに作られています。


ちなみに、「Django Packages : E-Commerce」の全パッケージ中でステータスが「Production/Stable」になっていたのは、

の 4つだったのですが、スターやフォーク数では「DJANGO-OSCAR」が圧倒的人気です。




ECパッケージの機能の中でも特に重要な機能の一つが「決済処理」ですが、多くの ECパッケージが、Pluggable なモジュール形式の「決済モジュール」を提供しています。PayPal や Stripe などの決済代行サービスに合わせた決済モジュールが個別に用意されているケースが多いのですが、ECパッケージ本体に組み込まれている場合や、別パッケージとしてソースコードが管理されている場合もあります。



 

決済モジュールの特徴

決済処理に特化したモジュールは「決済モジュール」と呼ばれ、Pluggable に差し替え可能な仕組みになっている場合が多く、決済代行サービスに合わせたものをチョイスして取り込むことができます。ECパッケージ本体やサードパーティ(コミュニティ)の決済モジュールで対応できない決済代行サービスを利用したい場合は、決済モジュール自体を自作する必要も出てきます。

決済処理の仕組み

ECサイトの決済処理の仕組みを簡単に図解すると、以下のようになります。

f:id:akiyoko:20160515172525p:plain
10 Safe and Popular Gateways for Online Payment Processing | InstantShiftを参考に作成)


ECサイトから見れば、決済代行サービスを窓口(ゲートウェイ)として利用することで、Visa や MasterCard のようなカード会社と直接やり取りすることなしに、決済処理ができるようになっています。


決済モジュールは以下の位置に配置され、API を通じて決済代行サービスとやり取りを行います。

f:id:akiyoko:20160522231309p:plain



決済モジュールは、ECパッケージのチェックアウト機能に合わせた決済モジュールが複数用意されている場合が多いので、使用する決済代行サービスに合わせてチョイスするのがベストです。


例えば、ECパッケージに「DJANGO-OSCAR」を使うのであれば、

django-oscar-datacashIntegration with the DataCash payment gateway
django-oscar-paypalIntegration with PayPal. This currently supports both Express Checkout and PayFlow Pro.
django-oscar-paymentexpressIntegration with the Payment Express payment gateway
django-oscar-accountsManaged accounts (can be used for giftcard functionality and loyalty schemes)
django-oscar-storesPhysical stores integration (opening hours, store locator etc)
django-oscar-ewayIntegration with the eWay payment gateway.
django-oscar-sagepay-directIntegration with "DIRECT" part of Sagepay's API

https://github.com/django-oscar/django-oscar#extensionsより)

が本家(django-oscar)から提供されており、これらは比較的信頼性も高いものと推測されます。その他にも、コミュニティが製作した決済モジュールも多々用意されているようですが、こちらの信頼性については個別に検証が必要です。


 
以上から、例えば、決済代行サービスに PayPal を利用する予定であれば「django-oscar-paypal」をまずは検討するのがよい、ということになります。しかしながら、PayPal を利用するにしても、使用する API の種類によっては(例えば日本国内では)対応できないという可能性もあるため、実際に検証が必要となります。



 

決済モジュールの選定

ECパッケージに依存しない決済モジュールも存在します。ECパッケージで用意された決済モジュールが決済代行サービスに対応していない場合などは、それらを使用すれば(カスタマイズは必要になると思いますが)、イチから自作しなくてもよくなるケースもあるでしょう。


こちらについても、Django Packages で比較検討してみることにしました。

Django Packages で比較

スター数の上位 5つをリストアップしました。
(「LFS - LIGHTNING FAST SHOP」は ECパッケージなので除外。加えて、「DJANGO-ZEBRA」は長年メンテされていなさそうなので除外しました。)


PACKAGEDJANGO-MERCHANTDJANGO-PAYPALDJ-STRIPEDJANGO-GETPAIDDJANGO-PAYMENTS
DescriptionA Django app to accept payments from various payment processors via Pluggable backends.A pluggable Django application for integrating PayPal Payments Standard or Payments ProDjango + Stripe Made EasyDjango payments processor.Universal payment handling for Django
Development StatusAlphaUnknownBetaProduction/Stablen/a
Last updatedJuly 8, 2015, 1:29 a.m.May 9, 2016, 1:51 p.m.May 11, 2016, 12:01 p.m.Jan. 25, 2016, 4:58 p.m.April 20, 2016, 12:05 p.m.
Version0.20.3.20.8.01.7.3n/a
Stars825307285167142
Repo Forks142831416357

Django Packages : Payment Processingより抜粋。2016年5月22日時点)


全体的に「Production/Stable」ステータスのものが少ない印象です。
また、Stripe や Braintree など、日本ではまだ使えない決済サービス向けに作られたものが多いようにも思いました。



 

まとめ

「ゼロからはじめる Django で ECサイト構築」の第一回として、ECパッケージの選定を行いました。

「DJANGO-OSCAR」が圧倒的人気で機能も充実しているようです。まずは、「DJANGO-OSCAR」の機能を実際に見ていきたいと思います。
また、Mezzanine 向けのショッピングカート機能を提供する「CARTRIDGE」も気になるところです。

今後は、この二つを中心に調査を続けていきます。


ゼロからはじめる Django で ECサイト構築(その2:Django Oscar の Sandbox サイト構築)

$
0
0

前回の記事「ゼロからはじめる Django で ECサイト構築(その1:ECパッケージの選定)」では、Django ベースの ECパッケージを選定し、「Django Oscar」が圧倒的人気で最有力候補であることが確認できました。


<過去記事>
akiyoko.hatenablog.jp


今回、「ゼロからはじめる Django で ECサイト構築」シリーズの第二回では、実際に、Django Oscar の Sandbox サイトを構築していくことにします。



f:id:akiyoko:20160531080056j:plain




 

Django Oscar について

概要

Django Oscar は、ECサイトを構築・運営するために必要な多くの機能が盛り込まれた、オープンソースで Django 製の ECパッケージです。ライセンスは修正BSDライセンス(New BSD license)で、商用利用も可能です。

github.com


機能の詳細については、次回以降にまとめていく予定です。


Sandbox とは

Sandbox とは、動作確認をするための開発者用のテスト環境のことを指します。
いわゆる「デモ環境」のことですね。

Django Oscar には、いろんな機能が組み込まれたデモサイトを簡単に立ち上げられるような仕組みが備わっていて、これを使うことで、Django Oscar の機能をお試しで検証することができます。




 

ECサイト構築に必要な三要素

さて、ECサイトを構築するためには、

  • 決済代行サービスのマーチャントアカウント
  • ECパッケージ
  • サーバ

の三つが必要最低限の要素として挙げられるでしょう。


まず一つ目の「決済代行サービスのマーチャントアカウント」は、PayPalWebPayなどの決済代行サービスのビジネスアカウント(売り手アカウント)を指します。Sandbox 環境においては、Sandbox(ややこしいですが、決済代行サービス側が用意してくれるテスト環境を指します)用のマーチャントアカウントを使用することで、実際に支払いをすることなく決済処理の流れをシミュレートすることができます。


今回の検証では、決済代行サービスとして PayPal を利用するのですが、Sandbox については次のように説明されています。

ペイパルでは、決済サービスの動作確認ができるテスト環境として、Sandboxを公開しています。
テスト用の「Buyer(買い手)」アカウントと、「Seller(売り手)」アカウントを作成し、サービスの導入から、決済の流れまで、詳細にシミュレーションすることができます。


Sandbox | ペイパルビジネスガイド - PayPal


二つ目の ECパッケージについては、前回の選定で最有力候補となった「Django Oscar」を使用します。なお、決済モジュールには「django-oscar-paypal」を使用することとします。


三つ目のサーバについては、今回の Sandbox サイトでは仮想環境(Vagrant 上の Ubuntu 仮想マシン)を利用します。




 

Sandbox サイトの構築手順

ここから実際に、Django Oscar の Sandbox サイトを構築していきます(2016/5/28 バージョン)。


構築する環境は以下となります。

  • サーバ:Ubuntu 14.04TLS(on Vagrant)
  • Python 2.7.6
  • Django 1.9.6(現時点の最新バージョン)
  • ECパッケージ:Django Oscar 1.2+(現時点の最新バージョン)
  • 決済モジュール:django-oscar-paypal 0.9.7(現時点の最新バージョン)

 
以降、次のような手順で進めていきます。

 

1. サーバの初期設定

私は通常、PyCharm Professional Edition の

  • Vagrant 連携機能
  • サーバとのソースコード同期機能
  • リモートデバッグ機能

などの機能を利用するために、PyCharm を使っています。なので、いつもなら

  • PyCharm の設定
    • Pure Python Project を作成(空っぽのプロジェクトを作成)
    • Vagrant連携

という流れで、PyCharm から Ubuntu サーバを立ち上げています。


<過去記事>
akiyoko.hatenablog.jp


手動でやるなら、以下のコマンドを実行します。

$ cd ~/PycharmProjects/oscar_sandbox/
$ vagrant init ubuntu/trusty64

仮想マシンに固定 IPアドレスを付けるために、Vagrantfile を書き換えます。

  config.vm.network "private_network", ip: "192.168.33.105"

仮想マシンを起動します。

$ vagrant up


Vagrant サーバに ssh で乗り込みます。

$ ssh vagrant@192.168.33.105

 

1.1. 最低限のライブラリをインストール
$ sudo apt-get update
$ sudo apt-get -y install python-dev git tree

 

1.2. MySQL をインストール

Ubuntu サーバに MySQL をインストールします。

$ sudo apt-get -y install mysql-server
(root/rootpass)
$ sudo apt-get -y install mysql-client libmysqlclient-dev python-mysqldb

$ mysql --version
mysql  Ver 14.14 Distrib 5.5.49, for debian-linux-gnu (x86_64) using readline 6.3

$ sudo mysql_install_db

### 文字化け対策(セクションの最後に以下の設定を追加)
### http://blog.snowcait.info/2014/06/04/mariadb-utf8/
$ sudo vi /etc/mysql/my.cnf
---
[mysqld]
  ・
  ・
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem

# Character set settings
character-set-server = utf8

[mysqldump]
  ・
  ・
---

$ sudo service mysql restart

$ sudo mysql_secure_installation
Enter current password for root (enter for none):
Change the root password? [Y/n] n
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y


 

1.3. データベースを作成

データベース、データベースユーザを作成します。
なお、データベース名は Djangoプロジェクト名と合わせて myproject とします。

データベース名myproject
データベースユーザmyprojectuser
データベースユーザパスワードmyprojectuserpass
$ mysql -u root -p
mysql> create database myproject character set utf8;
mysql> create user myprojectuser@localhost identified by "myprojectuserpass";
mysql> grant all privileges on myproject.* to myprojectuser@localhost;
mysql> flush privileges;
mysql> exit


 

1.4. pip をインストール

Python 2.7.9 以降であれば pip がバンドルされているのですが、Ubuntu 14.04LTS では Python 2.7.6 が標準なので、手動でインストールします。

「sudo apt-get -y install python-pip」でインストールすると pip のバージョンが古いので、get-pip.py で最新版を入れることにします。

$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo -H python get-pip.py
$ pip --version
pip 8.1.2 from /usr/local/lib/python2.7/dist-packages (python 2.7)


参考


 

1.5. virtualenv, virtualenvwrapper をインストール
### virtualenv, virtualenvwrapper をインストール
$ sudo -H pip install virtualenv virtualenvwrapper

### virtualenvwrapper の設定
$ cat << EOF >> ~/.bash_profile

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
EOF
$ cat << EOF >> ~/.bashrc

source /usr/local/bin/virtualenvwrapper.sh
export WORKON_HOME=~/.virtualenvs
EOF
$ source ~/.bashrc


 

2. Sandbox サイト(Django Oscar)の作成

2.1. Django Oscar プロジェクトを構築

Setting up the development environment — django-oscar 1.3 documentation
に従って、Oscar プロジェクトのインストールをします。

### Djangoプロジェクトの virtualenv 環境を設定して activate
$ mkvirtualenv myproject

### /opt/webapps 配下にプロジェクトの外箱を作成
$ sudo mkdir -p /opt/webapps/myproject
$ sudo chown -R `whoami`. /opt/webapps

### JPEG Support
### http://django-oscar.readthedocs.org/en/latest/internals/contributing/development-environment.html#jpeg-support
$ sudo apt-get -y install libjpeg-dev libfreetype6-dev zlib1g-dev
### make sandbox をした後であれば ↓ を実行して Pillow を再インストール
### pip install --no-cache-dir -I pillow
### http://qiita.com/tototoshi/items/7b74fe26eb7bf39be7b5

### MySQLライブラリのインストール
###($ pip install MySQL-python でも OK)
$ pip install mysqlclient

### Oscar プロジェクトを作成
$ cd /opt/webapps/myproject/

### 通常であれば、django-admin.py startproject . とするところを、今回は clone -> make sandbox として Sanbox サイトを作成
### http://django-oscar.readthedocs.org/en/latest/internals/getting_started.html
$ git clone https://github.com/django-oscar/django-oscar.git .


ここで、

###$ git checkout 1.2

として、最新の stable バージョン (1.2) に合わせようとしましたが、make sandbox 実行時に、

django.db.utils.OperationalError: (2013, 'Lost connection to MySQL server during query')

というエラーになってしまったので、master のままで試すことにしました(2016/5/28 時点)。


ちなみに、現時点の最新コミットは以下の通りです。

commit 156a4b814d540bb1c6216b757cfa4441b36f8077
Merge: e1a8ea7 de633f8
Author: Michael van Tellingen
Date: Wed Apr 13 09:03:37 2016 +0200

Merge pull request #2030 from crgwbr/fix_broken_py3_migrations

Fix makemigrations in Python 3

 

### MySQL用の設定変更
$ vi sites/sandbox/settings.py
<変更前>
---
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': location('db.sqlite'),
        'USER': '',
        'PASSWORD': '',
        'HOST': '',
        'PORT': '',
        'ATOMIC_REQUESTS': True
    }
}
---
  ↓
<変更後>
---
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'myprojectuserpass',
        'HOST': 'localhost',
        'PORT': '',
        'ATOMIC_REQUESTS': True
    }
}
---

### Sandbox プロジェクトを作成
### プロジェクトのディレクトリ構造は
### myproject/ (as <repository_root>)
### └─ sites/sandbox/ (as <django_project_root> also as <configuration_root>)
$ make sandbox


ちなみに、make sandbox の処理はこのようになっています。

Makefile(抜粋)

install:
    pip install -e . -r requirements.txt

build_sandbox:
    # Remove media
    -rm -rf sites/sandbox/public/media/images
    -rm -rf sites/sandbox/public/media/cache
    -rm -rf sites/sandbox/public/static
    -rm -f sites/sandbox/db.sqlite
    # Create database
    sites/sandbox/manage.py migrate
    # Import some fixtures. Order is important as JSON fixtures include primary keys
    sites/sandbox/manage.py loaddata sites/sandbox/fixtures/child_products.json
    sites/sandbox/manage.py oscar_import_catalogue sites/sandbox/fixtures/*.csv
    sites/sandbox/manage.py oscar_import_catalogue_images sites/sandbox/fixtures/images.tar.gz
    sites/sandbox/manage.py oscar_populate_countries
    sites/sandbox/manage.py loaddata sites/_fixtures/pages.json sites/_fixtures/auth.json sites/_fixtures/ranges.json sites/_fixtures/offers.json
    sites/sandbox/manage.py loaddata sites/sandbox/fixtures/orders.json
    sites/sandbox/manage.py clear_index --noinput
    sites/sandbox/manage.py update_index catalogue

sandbox: install build_sandbox

 
Sandbox の作成が完了したら、作成状況を確認してみます。

$ pip list | grep Django
Django (1.9.6)

$ pip list | grep django-oscar
django-oscar (1.3.dev0, /opt/webapps/myproject/src)

$ pip freeze
alabaster==0.7.8
apipkg==1.4
Babel==2.3.4
beautifulsoup4==4.4.1
coverage==3.7.1
coveralls==0.4.4
decorator==4.0.9
Django==1.9.6
django-debug-toolbar==1.4
django-extensions==1.6.1
django-extra-views==0.6.4
django-haystack==2.4.1
-e git+https://github.com/django-oscar/django-oscar.git@156a4b814d540bb1c6216b757cfa4441b36f8077#egg=django_oscar
django-tables2==1.0.7
django-treebeard==4.0.1
django-webtest==1.7.8
django-widget-tweaks==1.4.1
docopt==0.6.2
docutils==0.12
execnet==1.4.1
factory-boy==2.6.1
fake-factory==0.5.7
flake8==2.5.1
flake8-blind-except==0.1.0
flake8-debugger==1.4.0
funcsigs==1.0.2
ipaddress==1.0.16
ipdb==0.8.1
ipython==4.0.1
ipython-genutils==0.1.0
isort==4.2.2
Jinja2==2.8
MarkupSafe==0.23
mccabe==0.3.1
mock==1.3.0
mysqlclient==1.3.7
nose==1.3.7
pathlib2==2.1.0
pbr==1.10.0
pep8==1.7.0
pexpect==4.1.0
phonenumbers==7.4.1
pickleshare==0.7.2
Pillow==2.7.0
pockets==0.3
ptyprocess==0.5.1
purl==1.3
py==1.4.31
pycountry==1.8
pyflakes==1.0.0
Pygments==2.1.3
pyprof2calltree==1.3.2
pysolr==3.2.0
pytest==2.8.5
pytest-cache==1.0
pytest-cov==2.2.0
pytest-django==2.9.1
pytest-xdist==1.13.1
python-dateutil==2.5.3
pytz==2016.4
PyYAML==3.11
requests==2.7.0
simplegeneric==0.8.1
six==1.10.0
snowballstemmer==1.2.1
sorl-thumbnail==12.4a1
spec==0.11.1
Sphinx==1.3.3
sphinx-rtd-theme==0.1.9
sphinxcontrib-napoleon==0.4.3
sqlparse==0.1.19
tox==1.8.1
traitlets==4.2.1
Unidecode==0.4.19
uWSGI==2.0.12
virtualenv==15.0.1
waitress==0.9.0
WebOb==1.6.1
WebTest==2.0.17
Werkzeug==0.9.6
whitenoise==2.0.6
Whoosh==2.6.0
$ find . -name "*.pyc" -exec rm -rf {} \;
$ tree -a /opt/webapps/myproject/ -I ".git|docs|tests" -L 3
/opt/webapps/myproject/
├── AUTHORS
├── CHANGELOG.rst
├── CONTRIBUTING.rst
├── .coveragerc
├── Dockerfile
├── .dockerignore
├── .gitignore
├── gulpfile.js
│   ├── index.js
│   └── tasks
│       ├── default.js
│       ├── less.js
│       └── watch.js
├── LICENSE
├── lint.sh
├── .mailmap
├── Makefile
├── MANIFEST.in
├── package.json
├── README.rst
├── requirements_migrations.txt
├── requirements.txt
├── runtests.py
├── sandbox.yml
├── setup.cfg
├── setup.py
├── sites
│   ├── _fixtures
│   │   ├── auth.json
│   │   ├── comms.json
│   │   ├── offers.json
│   │   ├── order-events.json
│   │   ├── pages.json
│   │   ├── promotions.json
│   │   ├── range-products.csv
│   │   └── ranges.json
│   ├── README.rst
│   └── sandbox
│       ├── apps
│       ├── deploy
│       ├── fixtures
│       ├── __init__.py
│       ├── logs
│       ├── manage.py
│       ├── public
│       ├── README.rst
│       ├── settings_mysql.py
│       ├── settings_postgres.py
│       ├── settings.py
│       ├── settings_sphinx.py
│       ├── static
│       ├── templates
│       ├── test_migrations.sh
│       ├── update_latest.sh
│       ├── urls.py
│       ├── whoosh_index
│       └── wsgi.py
├── src
│   ├── django_oscar.egg-info
│   │   ├── dependency_links.txt
│   │   ├── PKG-INFO
│   │   ├── requires.txt
│   │   ├── SOURCES.txt
│   │   └── top_level.txt
│   └── oscar
│       ├── app.py
│       ├── apps
│       ├── core
│       ├── defaults.py
│       ├── forms
│       ├── __init__.py
│       ├── locale
│       ├── management
│       ├── models
│       ├── profiling
│       ├── static
│       ├── templates
│       ├── templatetags
│       ├── test
│       └── views
├── tox.ini
├── transifex.sh
├── .travis.yml
└── .tx
    └── config

29 directories, 56 files

ここで一旦、データベースをバックアップしておきます。

### http://weblabo.oscasierra.net/mysql-mysqldump-01/
### ちなみに、リストアするときは mysql -u root -p myproject < ~/myproject_init.dump
$ mysqldump --single-transaction -u root -p myproject > ~/myproject_init.dump


 

2.2. Runserver で起動
$ python sites/sandbox/manage.py runserver 0.0.0.0:8000

でサーバを起動して、
http://192.168.33.105:8000/
にブラウザからアクセスします。

f:id:akiyoko:20160529121316p:plain


ログインユーザ

username: superuser
email: superuser@example.com
password: testing

username: staff
email: staff@example.com
password: testing

f:id:akiyoko:20160529121332p:plain

f:id:akiyoko:20160529121348p:plain


疎通ができたら、Runserver を一旦停止します。


ちなみにここまでの設定では、決済モジュールの設定をしていないので、決済処理を完了することができなくなっています。

f:id:akiyoko:20160529122316p:plain

(住所や電話番号などのダミー情報は、US Address Generator - Fake Address, Random Address Generatorで生成したものを入力しました。)
f:id:akiyoko:20160529122334p:plain

f:id:akiyoko:20160529122349p:plain

このように、決済モジュール(payment gateway libraries)を設定してね、って怒られます。



以下、PyCharm を使う場合のメモです。PyCharm を使ってない方はすっ飛ばしてください。

  • PyCharm の設定
    • デプロイ先サーバ設定
    • ソースコードの同期
    • ローカル側でソースコードを Git管理
    • Project Interpreter の設定
    • Run/Debug設定(以下に詳細を記載)


Project ペインの manage.py ファイルで右クリック > [Create "manage"] を選択します。

Namemanage
Scriptsites/sandbox/manage.py
Script parametersrunserver 0.0.0.0:8000
Environment variablesPYTHONUNBUFFERED=1(デフォルトのまま)
Python interpreterProject Default (Remote Python 2.7.6 Vagrant VM at ~/PycharmProjects/oscar_sandbox (/home/vagrant/.virtualenvs/myproject/bin/python))
Working directory/opt/webapps/myproject
Path mappings - Local path/Users/akiyoko/PycharmProjects/oscar_sandbox
Path mappings - Remote path/opt/webapps/myproject


ここで、「Add content roots to PYTHONPATH」と「Add source roots to PYTHONPATH」のチェックを外します。

f:id:akiyoko:20160529125100p:plain

要するに、Script のパスに気をつけてね、ってことです。



各種設定を確認

Sandbox サイトの settings.py を確認すると、以下のドキュメントに書かれている、既存サイトに追加する場合に追加する必要のある設定が全て追加されています。
http://django-oscar.readthedocs.org/en/latest/internals/getting_started.html


sites/sandbox/settings.py(抜粋)

・
    ・
SITE_ID = 1・
    ・
TEMPLATE_CONTEXT_PROCESSORS = (
    "django.contrib.auth.context_processors.auth",
    "django.core.context_processors.request",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.static",
    "django.contrib.messages.context_processors.messages",
    # Oscar specific'oscar.apps.search.context_processors.search_form',
    'oscar.apps.promotions.context_processors.promotions',
    'oscar.apps.checkout.context_processors.checkout',
    'oscar.core.context_processors.metadata',
    'oscar.apps.customer.notifications.context_processors.notifications',
)

MIDDLEWARE_CLASSES = (
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
    # Allow languages to be selected'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    # Ensure a valid basket is added to the request instance for every request'oscar.apps.basket.middleware.BasketMiddleware',
    # Enable the ProfileMiddleware, then add ?cprofile to any# URL path to print out profile details#'oscar.profiling.middleware.ProfileMiddleware',
)
    ・
    ・
# Add another path to Oscar's templates.  This allows templates to be# customised easily.from oscar import OSCAR_MAIN_TEMPLATE_DIR
TEMPLATE_DIRS = (
    location('templates'),
    OSCAR_MAIN_TEMPLATE_DIR,
)
    ・
    ・
INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
    'django.contrib.flatpages',
    'django.contrib.staticfiles',
    'django.contrib.sitemaps',
    'django_extensions',
    # Debug toolbar + extensions'debug_toolbar',
    'apps.gateway',     # For allowing dashboard access'widget_tweaks',
]
from oscar import get_core_apps
INSTALLED_APPS = INSTALLED_APPS + get_core_apps()

# Add Oscar's custom auth backend so users can sign in using their email# address.
AUTHENTICATION_BACKENDS = (
    'oscar.apps.customer.auth_backends.EmailBackend',
    'django.contrib.auth.backends.ModelBackend',
)
    ・
    ・


INSTALLLED_APPS に

  • django.contrib.sites
  • django.contrib.flatpages

が追加されていて、MIDDLEWARE_CLASSES に

  • oscar.apps.basket.middleware.BasketMiddleware
  • django.contrib.flatpages.middleware.FlatpageFallbackMiddleware

が追加されていることが確認できます。



ちなみに、「TEMPLATE_CONTEXT_PROCESSORS」と「TEMPLATE_DIRS」を分けて記述している Sandbox の setteings.py の書き方は、Django 1.9 の書き方としては少し古いようですね。

Before Django 1.8 this setting was split between TEMPLATE_CONTEXT_PROCESSORS and TEMPLATE_DIRS.


http://django-oscar.readthedocs.org/en/latest/internals/getting_started.html



 

決済モジュールの導入手順

続けて、Django Oscar の Sandbox サイトに決済モジュールを組み込んでいきます。

決済代行サービスに「PayPal」を利用することを想定して、決済モジュールには「django-oscar-paypal」を選択することにします。


手順は以下の通りです。


参考
http://django-oscar-paypal.readthedocs.org/en/latest/


 

1. PayPal の Test API Credentials を取得

PayPal の決済モジュールを利用するには、「Test API Credentials」という PayPal の決済API を利用するための認証情報が必要となります。

「Test API Credentials」は、以下の 3セットのキー・バリューとなっています。

  • PAYPAL_API_USERNAME
  • PAYPAL_API_PASSWORD
  • PAYPAL_API_SIGNATURE



Test API Credentials を取得する前に、まずは PayPal のアカウントを取得します。本番ではビジネスアカウントが必要ですが、Sandbox では個人アカウントでも大丈夫です。


PayPal アカウントを取得した後に、「PayPal Developer」ページからログインします。
https://developer.paypal.com/
f:id:akiyoko:20160531003041p:plain

Sandbox アカウントではなく、通常の PayPal アカウントでログインします。
f:id:akiyoko:20160531003105p:plain

「DASHBOARD」をクリックします。
f:id:akiyoko:20160531003128p:plain

「Accounts」を選択します。
f:id:akiyoko:20160531003200p:plain

Sandbox 用の「Buyer アカウント(マーチャントアカウント)」と「Seller アカウント(買い手アカウント)」がデフォルトで用意されている(はずな)ので、Type が「BUSINESS」となっている方の Buyer アカウントの「Profile」をクリックします。
f:id:akiyoko:20160531003227p:plain

「API Credentials」タブから Test API Credentials を確認することができます。
f:id:akiyoko:20160531003251p:plain


参考(PayPal 公式)


参考(Test API Credentials)


参考(ビジネスアカウント)


 

2. django-oscar-paypal のインストール

Ubuntu サーバ側で、django-oscar-paypal をインストールします。

$ workon myproject
$ pip install django-oscar-paypal
  • django-localflavor==1.3
  • django-oscar-paypal==0.9.7

が追加されました。


 

3. INSTALLED_APPS に追加

sites/sandbox/settings.py に「paypal」を加えます。

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.admin',
    'django.contrib.flatpages',
    'django.contrib.staticfiles',
    'django.contrib.sitemaps',
    'django_extensions',
    # Debug toolbar + extensions'debug_toolbar',
    'paypal',
    'apps.gateway',     # For allowing dashboard access'widget_tweaks',
]


 

4. マイグレーション

以下のコマンドを実行して、django-oscar-paypal 系のテーブルを作成します。

$ python sites/sandbox/manage.py migrate --run-syncdb

Operations to perform:
  Synchronize unmigrated apps: reports_dashboard, messages, django_extensions, treebeard, gateway, communications_dashboard, reviews_dashboard, offers_dashboard, pages_dashboard, shipping_dashboard, haystack, promotions_dashboard, checkout, vouchers_dashboard, django_tables2, partners_dashboard, staticfiles, oscar, paypal, sitemaps, catalogue_dashboard, users_dashboard, search, debug_toolbar, widget_tweaks, dashboard, ranges_dashboard, orders_dashboard
  Apply all migrations: customer, promotions, shipping, wishlists, offer, admin, sessions, thumbnail, contenttypes, auth, payment, reviews, analytics, catalogue, flatpages, sites, address, basket, partner, order, voucher
Synchronizing apps without migrations:
  Creating tables...
    Creating table paypal_expresstransaction
    Creating table paypal_payflowtransaction
    Running deferred SQL...
Running migrations:
  No migrations to apply.
  Your models have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

Django 1.9 の場合は、「run-syncdb」オプションを付けないとテーブルが作成されないので要注意です。(最後の警告は無視して OK。対応したいのであれば、makemigrations を実行すればよい。)

参考
http://stackoverflow.com/a/34635951


ここで、

  • paypal_expresstransaction
  • paypal_payflowtransaction

というテーブルが追加されました。



ここでもう一度、データベースをバックアップしておきます。

$ mysqldump --single-transaction -u root -p myproject > ~/myproject_migrate_paypal.dump

 

5. settings を修正

ここからは、
http://django-oscar-paypal.readthedocs.org/en/latest/express.html#getting-started
を参考にして進めていきます。


https://github.com/django-oscar/django-oscar-paypal/blob/master/sandbox/settings.py
を参考に、settings.py を修正します。


sites/sandbox/settings.py の最後の方に、以下の設定を追加します。

・
    ・
# django-oscar-paypal# ===================

PAYPAL_SANDBOX_MODE = True
PAYPAL_CALLBACK_HTTPS = False
PAYPAL_API_VERSION = '119'

PAYPAL_API_USERNAME = ''
PAYPAL_API_PASSWORD = ''
PAYPAL_API_SIGNATURE = ''from django.utils.translation import ugettext_lazy as _
OSCAR_DASHBOARD_NAVIGATION.append(
    {
        'label': _('PayPal'),
        'icon': 'icon-globe',
        'children': [
            {
                'label': _('Express transactions'),
                'url_name': 'paypal-express-list',
            },
        ]
    })

# Try and import local settings which can be used to override any of the above.try:
    from settings_local import *
exceptImportError:
    pass


次に、sites/sandbox/settings_local.py に、「1. PayPal の Test API Credentials を取得」で取得したマーチャントアカウントの APIキーを設定します。

PAYPAL_API_USERNAME = 'xxxxxx-facilitator_api1.xxxxxx.xxx'
PAYPAL_API_PASSWORD = 'xxxxxxxxxxxxxxxx'
PAYPAL_API_SIGNATURE = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

 

6. urls.py を修正

https://github.com/django-oscar/django-oscar-paypal/blob/master/sandbox/urls.py
を参考に、sites/sandbox/urls.py を修正します。

<修正前>

・
    ・
from oscar.app import application
from oscar.views import handler500, handler404, handler403
    ・
    ・
# Prefix Oscar URLs with language codes
urlpatterns += i18n_patterns('',
    # Custom functionality to allow dashboard users to be created
    url(r'gateway/', include('apps.gateway.urls')),
    # Oscar's normal URLs
    url(r'', include(application.urls)),
)
    ・
    ・

  ↓
<修正後>

・
    ・
from oscar.app import application
from oscar.views import handler500, handler404, handler403
from paypal.express.dashboard.app import application as express_dashboard
    ・
    ・
# Prefix Oscar URLs with language codes
urlpatterns += i18n_patterns('',
    # PayPal Express integration
    url(r'checkout/paypal/', include('paypal.express.urls')),
    # Dashboard views for Express
    url(r'dashboard/paypal/express/', include(express_dashboard.urls)),
    # Custom functionality to allow dashboard users to be created
    url(r'gateway/', include('apps.gateway.urls')),
    # Oscar's normal URLs
    url(r'', include(application.urls)),
)
    ・
    ・


 

7. django-oscar-paypal のテンプレートファイルを修正

Django Oscar の basket(ショッピングカート)機能、および checkout(チェックアウト)機能で使われている各種テンプレートファイルに対して、以下の修正を行います。

  • Django 1.9 対応(django-oscar-paypal が Django 1.9 に対応していないため)
  • 体裁修正(django-oscar-paypal が Django Oscar のスタイルに対応していないため)


ここで、settings.py の設定が以下のようになっており、Sandbox プロジェクトの仕組み上、「sites/sandbox/templates/」 ->「src/oscar/templates/oscar/」の順にテンプレートファイルをルックアップし、それでも無ければ、INSTALLED_APPS でインストールしたアプリケーションのテンプレートファイルを参照するようになっています。

from oscar import OSCAR_MAIN_TEMPLATE_DIR
TEMPLATE_DIRS = (
    location('templates'),
    OSCAR_MAIN_TEMPLATE_DIR,
)

Sandbox プロジェクトでは、「src/oscar/templates/oscar/」配下に実ファイルを配置しているため、ライブラリが持っているテンプレートファイルによるオーバーライドが出来ないので注意が必要です。


 

1) ショッピングカート画面

django-oscar-paypal の Sandbox用に用意されているファイル
https://github.com/django-oscar/django-oscar-paypal/blob/master/sandbox/templates/basket/partials/basket_content.html
を sites/sandbox/templates/ 配下にコピーします。

$ cd /tmp/
$ git clone https://github.com/django-oscar/django-oscar-paypal.git
$ cd django-oscar-paypal/
$ git checkout 0.9.7
$ mkdir -p /opt/webapps/myproject/sites/sandbox/templates/basket/partials
$ cp -a sandbox/templates/basket/partials/basket_content.html /opt/webapps/myproject/sites/sandbox/templates/basket/partials/basket_content.html

2016/5/28 現時点の django-oscar-paypal のソースコードのままでは、以下のようにエラーが出てしまいます。

f:id:akiyoko:20160529145830p:plain

テンプレート内で、

{% load url from future %}

と書くと、Django 1.9 で動かした場合に、

'url' is not a valid tag or filter in tag library 'future'

というエラーが発生します。これは、Django1.9 以降では、future タグの url がなくなって、ビルトインのものを使うようになったからです。なので、Django1.9 以降では、url を load する必要は無く、

{% url 'checkout:preview' %}

とそのまま使えばよいです。


参考
https://www.bountysource.com/issues/29762758-django-1-9-compatibility-url-tag


要するに、django-oscar-paypal のテンプレートが Django 1.9 対応されていないのが原因なので、以下のように修正していきます。


sites/sandbox/templates/basket/partials/basket_content.html
<修正前>

{% extends 'oscar/basket/partials/basket_content.html' %}
{% load url from future %}
{% load i18n %}

{% block formactions %}
<divclass="form-actions">
	{% if anon_checkout_allowed or request.user.is_authenticated %}
        {% if basket.total_excl_tax > 0 %}
            <ahref="{% url 'paypal-redirect' %}"><imgsrc="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"align="left"style="margin-right:7px;"></a>
        {% endif %}
	{% endif %}
	<ahref="{% url 'checkout:index' %}"class="pull-right btn btn-large btn-primary">{% trans "Proceed to checkout" %}</a></div>
{% endblock formactions %}

  ↓
<修正後>

{% extends 'oscar/basket/partials/basket_content.html' %}
{#{% load url from future %}#}
{% load i18n %}

{% block formactions %}
<divclass="form-actions">
	{% if anon_checkout_allowed or request.user.is_authenticated %}
        {% if basket.total_excl_tax > 0 %}
            <ahref="{% url 'paypal-redirect' %}"><imgsrc="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"align="left"style="margin-right:7px;"></a>
        {% endif %}
	{% endif %}
	<ahref="{% url 'checkout:index' %}"class="pull-right btn btn-large btn-primary">{% trans "Proceed to checkout" %}</a></div>
{% endblock formactions %}

上記の対応後、ショッピングカート画面を確認すると、以下のように表示が少し崩れてしまっています。

f:id:akiyoko:20160529150928p:plain


こちらは、Django Oscar 側のテンプレートのスタイルの当て方が変わったのに、django-oscar-paypal の Sandbox 用のテンプレート側がまだ対応できていないことが原因のようです。

そこで、src/oscar/templates/oscar/basket/partials/basket_content.html を参考にして、以下のようにテンプレートファイルを修正します。

<再修正後>

{% extends 'oscar/basket/partials/basket_content.html' %}
{#{% load url from future %}#}
{% load i18n %}

{% block formactions %}
    <divclass="form-actions"><divclass="row"><divclass="col-sm-8">
                {% if anon_checkout_allowed or request.user.is_authenticated %}
                {% if basket.total_excl_tax > 0 %}
                <ahref="{% url 'paypal-redirect' %}"><imgsrc="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"align="left"style="margin-right:7px;"></a>
                {% endif %}
                {% endif %}
            </div><divclass="col-sm-4"><ahref="{% url 'checkout:index' %}"class="btn btn-lg btn-primary btn-block">{% trans "Proceed to checkout" %}</a></div></div></div>
{% endblock formactions %}

これで、きちんと表示されるようになりました。
f:id:akiyoko:20160529151517p:plain


 

2) チェックアウト画面

同じように、
https://github.com/django-oscar/django-oscar-paypal/blob/master/sandbox/templates/checkout/payment_details.html
を sites/sandbox/templates/ 配下にコピーします。

$ cd /tmp/django-oscar-paypal/
$ mkdir -p /opt/webapps/myproject/sites/sandbox/templates/checkout
$ cp -a sandbox/templates/checkout/payment_details.html /opt/webapps/myproject/sites/sandbox/templates/checkout/payment_details.html

こちらも、同様のエラーが出るので、
f:id:akiyoko:20160529152118p:plain


以下のように修正を加えます。

sites/sandbox/templates/checkout/payment_details.html
<修正前>

{% extends 'oscar/checkout/payment_details.html' %}
{% load url from future %}
{% load i18n %}

{% block payment_details %}
    <divclass="well"><divclass="sub-header"><h3>{% trans "PayPal Express" %}</h3></div><p>{% trans "Click on the below icon to use Express Checkout but where the shipping address and method is already chosen on the merchant site." %}</p><divstyle="overflow:auto"><ahref="{% url 'paypal-direct-payment' %}"title="{% trans "Pay with PayPal" %}"><imgsrc="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif"align="left"style="margin-right:7px;"></a>&nbsp;</div></div><divclass="well"><divclass="sub-header"><h3>{% trans "PayPal PayFlow Pro" %}</h3></div><formmethod="post"action="{% url 'checkout:preview' %}"class="form-stacked">
            {% csrf_token %}
            <h4>{% trans "Bankcard" %}</h4>
            {% include "partials/form_fields.html" with form=bankcard_form %}
            <h4>{% trans "Billing address" %}</h4>
            {% include "partials/form_fields.html" with form=billing_address_form %}
            <divclass="form-actions"><buttontype="submit"class="btn btn-large btn-primary">{% trans "Continue" %}</button></div></form></div>

{% endblock %}

  ↓
<修正後>

{% extends 'oscar/checkout/payment_details.html' %}
{#{% load url from future %}#}
{% load i18n %}

{% block payment_details %}
    <divclass="well"><divclass="sub-header"><h3>{% trans "PayPal Express" %}</h3></div><p>{% trans "Click on the below icon to use Express Checkout but where the shipping address and method is already chosen on the merchant site." %}</p><divstyle="overflow:auto"><ahref="{% url 'paypal-direct-payment' %}"title="{% trans "Pay with PayPal" %}"><imgsrc="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif"align="left"style="margin-right:7px;"></a>&nbsp;</div></div><divclass="well"><divclass="sub-header"><h3>{% trans "PayPal PayFlow Pro" %}</h3></div><formmethod="post"action="{% url 'checkout:preview' %}"class="form-stacked">
            {% csrf_token %}
            <h4>{% trans "Bankcard" %}</h4>
            {% include "partials/form_fields.html" with form=bankcard_form %}
            <h4>{% trans "Billing address" %}</h4>
            {% include "partials/form_fields.html" with form=billing_address_form %}
            <divclass="form-actions"><buttontype="submit"class="btn btn-large btn-primary">{% trans "Continue" %}</button></div></form></div>

{% endblock %}

f:id:akiyoko:20160529152616p:plain

ここでは詳しく触れませんが、日本では「PayPal PayFlow Pro」は使えないので、最終的なテンプレートファイルは以下のようにしておきます。

<再修正後>

{% extends 'oscar/checkout/payment_details.html' %}
{#{% load url from future %}#}
{% load i18n %}

{% block payment_details %}
    <divclass="well"><divclass="sub-header"><h3>{% trans "PayPal Express" %}</h3></div><p>{% trans "Click on the below icon to use Express Checkout but where the shipping address and method is already chosen on the merchant site." %}</p><divstyle="overflow:auto"><ahref="{% url 'paypal-direct-payment' %}"title="{% trans "Pay with PayPal" %}"><imgsrc="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif"align="left"style="margin-right:7px;"></a>&nbsp;</div></div>
{% endblock %}

f:id:akiyoko:20160529152636p:plain



 

3) PayPal からのリダイレクト画面

続いて、PayPal での処理処理が終わったときにリダイレクトされてくる画面のテンプレートファイルを修正します。これまで同様に、

  • Django 1.9 対応
  • 体裁修正

の対応を行います。

$ cp -r /home/vagrant/.virtualenvs/myproject/lib/python2.7/site-packages/paypal/templates/* /opt/webapps/myproject/sites/sandbox/templates/
$ rm -rf /opt/webapps/myproject/sites/sandbox/templates/paypal/payflow

$ tree sites/sandbox/templates/paypal/
sites/sandbox/templates/paypal/
└── express
    ├── dashboard
    │   ├── transaction_detail.html
    │   └── transaction_list.html
    └── preview.html

sites/sandbox/templates/paypal/express/preview.html
<修正前>

{% extends "checkout/preview.html" %}
{% load currency_filters %}
{% load i18n %}
{% load url from future %}
{% load thumbnail %}

{# Null out the actions as they can't be used here #}
{% block shipping_address_actions %}{% endblock %}
{% block shipping_method_actions %}{% endblock %}
{% block order_contents_actions %}{% endblock %}

{% block payment_method %}
    <divclass="span6"><divclass="sub-header"><h2>{% trans "Payment" %}</h2></div><divclass="well well-success"><h4>{% trans "PayPal" %}</h4><p>
                {% blocktrans with amt=paypal_amount|currency email=paypal_user_email %}
                    {{ amt }} will be deducted from your PayPal account, registered 
                    to email: {{ email }}.
                {% endblocktrans %}
            </p></div></div>
{% endblock %}
    ・
    ・

  ↓
<修正後>

{% extends "checkout/preview.html" %}
{% load currency_filters %}
{% load i18n %}
{#{% load url from future %}#}
{% load thumbnail %}

{# Null out the actions as they can't be used here #}
{% block shipping_address_actions %}{% endblock %}
{% block shipping_method_actions %}{% endblock %}
{% block order_contents_actions %}{% endblock %}

{% block payment_method %}
    <divclass="col-sm-6"><divclass="sub-header"><h2>{% trans "Payment" %}</h2></div><divclass="well well-success"><p>{% blocktrans with amount=order_total.incl_tax|currency %}<strong>{{ amount }}</strong> will be debited from your bankcard.{% endblocktrans %}</p><divclass="alert-actions"><ahref="{% url 'checkout:payment-details' %}"class="btn">{% trans "Change payment details" %}</a></div></div></div>
{% endblock payment_method %}
    ・
    ・


 

4) ダッシュボード画面

Django Oscar のダッシュボード画面を使う場合は、以下の 2ファイルに Django 1.9 対応の修正を加える必要があります。


sites/sandbox/templates/paypal/express/dashboard/transaction_list.html

{% extends 'dashboard/layout.html' %}
{% load currency_filters %}
{% load i18n %}
{#{% load url from future %}#}
    ・
    ・


f:id:akiyoko:20160529154701p:plain


sites/sandbox/templates/paypal/express/dashboard/transaction_detail.html

{% extends 'dashboard/layout.html' %}
{% load currency_filters %}
{% load i18n %}
{#{% load url from future %}#}
    ・
    ・

f:id:akiyoko:20160529154718p:plain


以上で、Django Oscar の Sandbox サイトを構築するまでの作業は終了です。



GitHub にも修正内容をアップしたので、こちらも参照してください。
GitHub - akiyoko/oscar_sandbox




 

まとめ

やや細かな修正内容まで言及してしまいましたが、Django Oscar の Sandbox サイトを構築して、決済モジュールを導入するまでの手順を紹介しました。

これで、Django Oscar のいろいろな機能を試すことができるようになりました。次回は、この Sandbox サイトを使って、Django Oscar の ECサイトとしての機能を検証していきます。

ゼロからはじめる Django で ECサイト構築(その3:Django Oscar の機能を調べる)

$
0
0

Django 製の ECパッケージの決定版とも言える Django Oscarは、公式ドキュメントによると、以下の 16 個の機能(Django App)から構成されています。
Oscar Core Apps explained — django-oscar 1.3 documentation



機能
概要
備考
Address住所登録配送先住所や請求先住所を管理する
Analyticsアナリティクス商品およびユーザーについてのアナリティクスが利用できる
Basketバスケットショッピングカート機能が利用できる
Catalogueカタログ商品カテゴリを管理する
Checkout決済手続き特定のフローに沿って決済手続きができる
Customer顧客管理在庫切れアラートやメール送信など、顧客とのやり取りを行う。他にも、メンバーシップやマイページのほとんどの機能がここに含まれる
Dashboardダッシュボード商品カタログ管理、商品注文管理、在庫・出庫管理、オファー管理などのバックオフィス機能のためのダッシュボード。Django admin サイトの代わりとして利用する
Offersオファー柔軟な条件のディスカウントを設定することができる
Order商品注文在庫数のチェックロジック、ディスカウントや配送料を含めた料金計算ロジックを提供する。画面は無い
Partnerパートナー商品の仕入先パートナー(Supplier)を登録したり、在庫・出庫パートナー(Fulfilment Partner)が利用する情報を提供したりする機能。SKU、在庫数、価格などが記録された在庫元帳(Stockrecord)、税率ポリシーや在庫ポリシーを持つストラテジー(Strategy)を管理することもできる。なお、在庫元帳とストラテジーから、商品を購入するのに必要な情報(PurchaseInfo)を取得する
Payment購入情報特定の決済代行サービスのための機能を利用することができる
Promotions広告広告のためのコンテンツブロックを作成し、特定の位置(トップページ、検索結果ページなど)に表示することができる
Search商品検索商品検索機能が利用できる
Shipping配送料計算配送先住所やショッピングカートの合計重量、その他いろいろな条件に応じて、自動的に配送料の計算をすることができる(ように設計されている) *1
Voucherバウチャーいろいろなタイプのクーポンコードを設定することができる
Wishlistsウィッシュリストほしい物リストが利用できる





今回は、前回構築した Django Oscar の Sandbox サイトを実際に動かしながら、Django Oscar の機能の一覧を調べていくことにします。


f:id:akiyoko:20160611012326j:plain





 

メンバーシップ

アカウント登録、退会、パスワード変更、ログイン、ログアウトの機能はひと通り揃っています。


 

アカウント登録

メールアドレスをベースにしたアカウント登録をすることができます。基本的なバリデーションはデフォルトで実装されています。

f:id:akiyoko:20160611113759p:plain

退会

少しわかりにくいですが、退会は、プロフィールページ(右上の[Account]>[Profile]で遷移)から[Delete Profile]を押下することでアカウントを削除することができます。

f:id:akiyoko:20160608011151p:plain
f:id:akiyoko:20160608004823p:plain

パスワード変更

パスワード変更もプロフィールページから操作することができます。

f:id:akiyoko:20160608011011p:plain
f:id:akiyoko:20160608071145p:plain

上記の方法とは別に、ログインページからもパスワードの変更(リセット)が可能です。

f:id:akiyoko:20160608004522p:plain

パスワードリセットのためのメールを送信することができます。
f:id:akiyoko:20160608071816p:plain

You're receiving this e-mail because you requested a password reset for your user account at example.com.


Please go to the following page and choose a new password:

http://example.com/en-gb/password-reset/confirm/Mw/4ck-c1f54b78fdaa9e31e057/

メール本文のリンクをクリックすると、パスワード変更ページに遷移します。

f:id:akiyoko:20160608071558p:plain

ログイン

Sandbox では、ログインとアカウント登録は、同一画面で行うように実装されています。

f:id:akiyoko:20160608011309p:plain

ログインせずに、ゲストとして商品を検索したり商品を注文したり *2することも可能です。

ログアウト

任意でログアウトも可能です。

f:id:akiyoko:20160608072131p:plain

 

マイページ

右上の[Account]からアカウントごとのページ(いわゆるマイページ)に遷移することができ、そこでは以下の機能を利用することができます。


f:id:akiyoko:20160608013201p:plain

プロフィール(Profile)

プロフィールページでは、氏名やメールアドレス、アカウント登録日時を表示できるほか、パスワード変更や退会を行うことができます。

f:id:akiyoko:20160608213427p:plain

注文履歴(Order History)

商品注文の履歴一覧、および詳細を確認することができます。
また、注文履歴の詳細画面から再注文をすることもできます。

f:id:akiyoko:20160609074548p:plain


登録済み住所一覧(Address Book)

登録した住所は、デフォルトの配送先住所(shipping address)、デフォルトの請求先住所(billing address)として設定しておき、商品注文時に再利用することができます。

f:id:akiyoko:20160611165642p:plain

メール一覧(Email History)

システムから送信されるメールの一覧を確認することができます。

f:id:akiyoko:20160610004545p:plain

在庫切れアラート(Product Alerts)

在庫切れになっている商品の詳細画面から[Notify me]ボタンを押下することで、サイト管理者にアラートを通知することができます。
f:id:akiyoko:20160610030515p:plain

マイページの[Product Alerts]から、通知した在庫切れアラートの一覧とそのステータス(サイト管理者が変更する)を確認したり、アラートを自らキャンセルしたりすることができます。
f:id:akiyoko:20160610030538p:plain

再入荷通知(Notifications)

在庫切れアラートに対するサイト管理者からのレスポンスとして、再入荷通知が行われます。
f:id:akiyoko:20160609074655p:plain

ウィッシュリスト(Wish Lists)

商品検索時にウィッシュリスト(ほしい物リスト)に入れていた商品を確認することができます。

リストは複数作成でき、それぞれのリストに名前を付けることができます。

f:id:akiyoko:20160608214516p:plain
f:id:akiyoko:20160608214545p:plain

 

商品紹介

商品紹介機能には、以下のようなサブ機能があります。

 

商品カテゴリ別表示

Sandbox サイト構築時に、ダミーの商品が 200点ほど自動的に登録されます。それぞれの商品にはカテゴリが付けられていて、商品カテゴリ別の一覧表示をすることができます。

f:id:akiyoko:20160608215231p:plain

商品検索

右上の検索窓から、商品のキーワード検索をすることができます。ちなみに、検索のバックエンドはプラガブルに入れ替え可能で、デフォルトで Haystackの各種検索エンジンを利用することができます。

f:id:akiyoko:20160608204907p:plain


商品の並び替え

商品検索をした後、以下の条件で並べ替えをすることができます。

  • キーワードへの関連性(Relevancy)
  • ユーザー評価の高い順(Customer rating)
  • 価格の高い順(Price high to low)
  • 価格の低い順(Price low to high)
  • タイトルの昇順(Title A to Z)
  • タイトルの降順(Title Z to A)

f:id:akiyoko:20160608204132p:plain



レビュー(ユーザー評価)

商品詳細ページで、レビュー(ユーザー評価)を書き込むことができます。
レビューの公開設定は、サイトの設定で承認制にすることも可能です。

f:id:akiyoko:20160608082137p:plain


レコメンド(おすすめ商品)

商品詳細ページの下の方に、おすすめ商品一覧(Recommended items)が表示されます。なお、Sandbox では、おすすめ商品はダッシュボード上でサイト管理者が手動で設定する仕組みになっています。

f:id:akiyoko:20160610103746p:plain


最近チェックした商品一覧

商品詳細ページの下の方に、最近チェックした商品一覧(Recommended items)が自動的に表示されます。

f:id:akiyoko:20160610103851p:plain



商品注文

商品注文としては、次の機能が含まれています。

 

ショッピングカート(Basket)

Amazon での「カート」、楽天市場での「買い物カゴ」と同等の機能が使えます。

商品詳細ページの[Add to basket]ボタンを押下することで、ショッピングカートに商品を追加することができます。

f:id:akiyoko:20160609073056p:plain

右上の[View basket]ボタンから、カートの中身をチェックすることができます。

f:id:akiyoko:20160609073117p:plain

ショッピングカートはこのように表示されます。

f:id:akiyoko:20160609073312p:plain

ショッピングカートの状態(アイテムの中身)は Cookie に保存され、Sandbox のデフォルト設定では一週間保持されることになります。



商品注文(Order)

ショッピングカートの状態に応じて、適切なディスカウントが自動的に適用されます。また、ユーザーに入力されたクーポンコードによるディスカウントについてもここで合わせて計算されます。

f:id:akiyoko:20160609073312p:plain

なお、通常の商品注文だけではなく、プレオーダー(予約注文)やバックオーダー(在庫切れ商品の取り寄せ注文)も可能です。また設定次第で、ゲスト注文(アカウント登録せずに商品注文すること)を許可することもできます。



決済手続き(Checkout)

Oscar の決済手続きは通常、以下のステップに沿って進められます。

1.ゲスト注文不可ならアカウント登録へ(ログイン済みの場合はスキップ)
   ↓
2.配送先入力
   ↓
3.配送方法選択(配送方法が一つのみの場合はスキップ)
   ↓
4.決済方法選択
   ↓
(PayPal ページにリダイレクト)
   ↓
(PayPal 買い手アカウントで認証して、決済内容を承認)
   ↓
5〜7.プレビュー & 決済内容詳細表示 & 注文確定(支払い)
   ↓
8.「ご注文ありがとうございます」

Checkout — django-oscar 1.3 documentationを参考に改編)


商品の決済手続きをする場合は、ショッピングカートページから「決済手続きに進む(Proceed to checkout)」ボタンを押下します。
f:id:akiyoko:20160609073349p:plain

(ログイン済みなので自動的に)配送先入力ステップに進みます。ここではデフォルトの配送先を選択します。
f:id:akiyoko:20160609073426p:plain

配送方法選択ステップはスキップされ、決済方法選択に進みます。
ちなみに今回は、Sandbox 構築時に決済モジュールとして PayPal しか設定していないため、ここでは PayPal 以外の選択肢がありません。
f:id:akiyoko:20160609073446p:plain

PayPal のログインページにリダイレクトされます。ここで PayPal の買い手アカウントでログインして、
f:id:akiyoko:20160609073647p:plain

決済内容を承認すると、
f:id:akiyoko:20160609073709p:plain

ECサイトのプレビューページに戻ってきます(決済はまだ確定していません)。

プレビューページの「注文確定(Place order)」ボタンを押下すると、支払いが完了します。
f:id:akiyoko:20160609073732p:plain

最後に確認ページが表示されます。
f:id:akiyoko:20160609073807p:plain


 

ダッシュボード(Dashboard)

ダッシュボードでは、商品カタログ管理、商品注文管理、在庫・出庫管理、オファー管理などのバックオフィス機能を利用することができます。

ダッシュボードのホーム画面には、指標となるデータがまとめて一覧表示されています。

f:id:akiyoko:20160610022412p:plain


ダッシュボードで利用できる機能としては、主に以下のようなものがあります。


 

商品カタログ管理(Catalogue)

商品カタログ管理機能では、単に商品を登録するだけでなく、様々な付加情報を設定することができます。

商品カテゴリ登録(Categories)

カテゴリとサブカテゴリを親子関係で紐付けることで、ツリー構造の商品カテゴリを実現することができます。Structure には、親カテゴリ、子カテゴリのほか、スタンドアロンの 3種類のいずれかを指定することができます。

なお、商品カテゴリは、主にナビゲーションのためだけに使用されます。


最上位の商品カテゴリは、[Catalogue]>[Categories]から管理します。

f:id:akiyoko:20160609071117p:plain

[Number of child categories]のリンクか、[Actions]>[Edit children]から辿ってサブカテゴリを編集することができます。


商品登録(Products)

[Catalogue]>[Products]で移動できる商品一覧ページから、商品を登録・編集することが可能です。

ちなみに、商品一覧ページには在庫数が表示されておらず、少し不便です。私個人的にはデフォルトで表示させてほしいところです。

f:id:akiyoko:20160609071138p:plain

商品は、事前に作成した「商品タイプ(Product type)」に紐付ける必要があります。


商品を選択後、[Stock and pricing]タブから仕入先パートナーや在庫数、通貨、価格を設定したり、[Upselling]タブからレコメンド(おすすめ商品)を設定したりすることができます。

f:id:akiyoko:20160611142403p:plain
f:id:akiyoko:20160610030319p:plain


 

在庫・出庫管理(Fulfilment)

在庫・出庫のために必要な情報を提供します。

商品注文管理(Orders)

[Fulfilment]>[Orders]から、商品注文の一覧を確認することができます。

ユーザー側で決済まで完了した商品注文は「Pending」ステータスになっているため、例えば、出庫の受付が済んだら「Being processed」に、配送が完了したら「Complete」に、というふうにステータスを切り替えることができます(手動で切り替えます)。
f:id:akiyoko:20160609081752p:plain

パートナー登録(Partners)

[Fulfilment]>[Partners]から、パートナーを作成したりパートナー一覧を確認したりすることができます。

パートナーには、ユーザーを任意で紐付けることができます。
f:id:akiyoko:20160609081831p:plain

顧客管理(Customers)

ユーザー管理(Customers)

[Customers]>[Customers]から、ユーザーごとの注文履歴や登録済みの住所、商品レビューの一覧などの情報を確認できるほか、パスワードリセットのためのメールを送信するボタンも用意されています。
f:id:akiyoko:20160609082251p:plain


在庫切れアラート管理(Stock alert requests)

[Customers]>[Stock alert requests]から、ユーザーからリクエストされた在庫切れアラートの一覧を確認することができます。
f:id:akiyoko:20160610031030p:plain


オファー管理(Offers)

オファー管理では、ディスカウントとバウチャーの管理をすることができます。

 

ディスカウント登録(Offers)

[Offers]>[Offers]から、ディスカウントを登録・編集できます。
f:id:akiyoko:20160609071005p:plain

Sandbox にデフォルトで登録されている以下の三種類のディスカウントのほか、ボリュームディスカウントなど柔軟な条件のディスカウントを設定することができます。

  • 1)規定個数以上買えば 1つ無料
    • ショッピングカートに 規定個数以上の商品を入れれば、その中で最も価格が安い商品が 1つ無料になるというタイプのディスカウントです。デフォルトの「Normal site offer」は、3個以上で 1つ無料という設定になっています。
  • 2)購入後特典(deferred benefit)
    • 購入後にポイントがもらえる的なディスカウントも設定可能です。Sandbox の「Deferred benefit offer」の説明には「商品を買ったら名前が Barry になるよ」というのが書かれているのですが、イギリスのギャグ(?)なのでしょうか。。(ちなみに、本当に購入後にユーザー名が Barry になってしまいます 笑)
  • 3)配送料無料

f:id:akiyoko:20160609071038p:plain


クーポンコード登録(Vouchers)

[Offers]>[Vouchers]から、クーポンコードを登録・編集することができます。ディスカウントは条件に応じて自動的に適用されるのに対し、クーポンコードは、ユーザーがコードを適宜入力する必要があります。


クーポンコードの登録にあたってはいろいろ柔軟な指定ができるようになっていて、例えば、それぞれのクーポンコードの使用制限について、以下の中から選択することができます。

  • 誰でも一回だけ使用可
  • 誰でも何回でも使用可
  • 先着一名のみ一回だけ使用可

また、割引きの種類については以下の中から選択可能です。

  • パーセント指定で割引
  • 金額指定で割引
  • 配送料のパーセント指定で割引
  • 配送料の金額指定で割引
  • 配送料が固定金額に

f:id:akiyoko:20160609071209p:plain
f:id:akiyoko:20160609071242p:plain


コンテンツ管理(Content)

アバウトページなどの固定ページを編集できるほか、[Content]>[Reviews]からユーザーレビューを確認することもできます。

f:id:akiyoko:20160609082027p:plain



レポート出力(Reports)

レポート出力機能では、様々なレポートを出力することができます。

f:id:akiyoko:20160611151345p:plain


決済状況管理(PayPal)

こちらは決済モジュールに django-paypalを利用した場合に使えるようになる機能ですが、[PayPal]>[Express transactions]から、ユーザーが PayPal 決済のトランザクションで使用した決済API のレスポンスの一覧および詳細を確認することができます。

これにより、決済処理中のエラーをトラッキングして解決に役立てることができるようになります。

f:id:akiyoko:20160609082133p:plain
f:id:akiyoko:20160609082200p:plain



 

まとめ

もちろん今回調査した機能以外にも、様々な機能が Django Oscar にはデフォルトで備わっています。しかしながら、今回の調査結果で分かるように、Django Oscar には、ECサイトを運営する上で必要となる基本機能はだいたい揃っていると考えてよいでしょう。


あとは、日本で Django Oscar を利用して ECサイトを構築したときに、日本の商習慣に合わせたカスタマイズ、ローカライズが必要になってくると考えられます。そこは追々やっていくとして、今後は、Oscar の機能をもう少し深追いしてみたいと思います。

*1:How to configure shipping — django-oscar 1.3 documentation

*2:ゲスト注文を許容するかどうかは設定次第

Django ORM の select_related, prefetch_related の挙動を詳しく調べてみた

$
0
0

Django ORM の QuerySet には、select_related および prefetch_related というメソッドがありますが、イマイチ使い勝手がよく分からなかったりします。


公式ドキュメントにはこう書いてありますが、

select_related works by creating an SQL join and including the fields of the related object in the SELECT statement. For this reason, select_related gets the related objects in the same database query. However, to avoid the much larger result set that would result from joining across a ‘many’ relationship, select_related is limited to single-valued relationships - foreign key and one-to-one.

prefetch_related, on the other hand, does a separate lookup for each relationship, and does the ‘joining’ in Python. This allows it to prefetch many-to-many and many-to-one objects, which cannot be done using select_related, in addition to the foreign key and one-to-one relationships that are supported by select_related.


select_related は、JOIN 句を作って、SELECT 句に関連するオブジェクトのフィールドを含めることによって動作する。これにより、select_related は 1本のデータベースクエリで関連オブジェクトを取得することができる。しかしながら、多くのリレーション先を辿って JOIN することで大規模な結果セットを取得してしまうことを避けるために、select_related は、foreign key や one-to-one といった「対一」リレーションのみを JOIN する。

一方、prefetch_related は、それぞれのリレーションに対して別々の参照を行い、Python コードで JOIN(相当の処理)を行う。これによって、select_related によって取得できる foreign key や one-to-one リレーションのオブジェクトだけではなく、select_related では取得不可能な many-to-many や many-to-one リレーションのオブジェクトの先取り(prefetch)をすることができる。


(akiyoko 訳)

https://docs.djangoproject.com/ja/1.9/ref/models/querysets/#select-related
https://docs.djangoproject.com/ja/1.9/ref/models/querysets/#prefetch-related


よく分からないですよね。


そこで今回は、select_related, prefetch_related を使うことでどのようなメリットがあるのかを確認するためにその挙動を詳しく調べてみたので、その結果をまとめてみたいと思います。



少し長いので、結論(分かったこと)から先に書きます。


分かったこと

Django ORM について

  • 1)多対一、一対一のリレーション先のオブジェクトはフィールドにアクセスした時点でクエリが発行される
    • クエリ発行後は取得したオブジェクトがキャッシュされるため、それ以降のクエリは発行されない
    • リレーション先のレコードが存在しなくても NotFound は発生しない
  • 2)一対多、多対多のリレーション先のオブジェクト群は、(all や filter で)アクセスする度にクエリが発行される
    • リレーション先のレコードが存在しなくても NotFound は発生しない

select_related について

  • 3)select_related を使うことで、一度のクエリで多対一、一対一のリレーション先のオブジェクトを取得してキャッシュしてくれる
    • null=False(デフォルト) の ForeignKey の場合は INNER JOIN で結合
    • null=True の ForeignKey の場合は LEFT OUTER JOIN で結合
  • 4)select_related の引数を指定しない場合は、多対一、一対一になっているリレーション先を全て取得してくれるのではなく、null=False の ForeignKey のみが取得対象

prefetch_related について

  • 5)prefetch_related を使うことで、先行してクエリを発行して、一対一、多対一、一対多、多対多のリレーション先のオブジェクト(群)を取得してキャッシュしてくれる
    • ただし、クエリの総数は減らない

注意点

  • select_related, prefetch_related の引数は明示的に指定しよう!



 

検証内容

今回は、一対一のリレーションの検証はしていません。 *1

検証環境

  • Ubuntu 14.04.4 LTS
  • Python 2.7.6
  • Django 1.9.8
  • MySQL 5.5.50

サンプルテーブル

ブログの投稿を想定したいくつかのテーブル群を検証に使用します。
ブログ投稿(blogpost)とブログ画像(blogimage)が多対一、ブログ投稿と投稿者(auth_user)が多対一、ブログ投稿とブログカテゴリが多対多のリレーションを持っていると仮定します。

以下は、論理モデルを ER図にしたものです。

f:id:akiyoko:20160803233339p:plain


参考までに、実際に作成したテーブルから、物理モデルの ER図を自動出力したものが以下になります。 *2

f:id:akiyoko:20160803071330p:plain


事前準備

Mezzanine プロジェクトの開発環境を PyCharm で設定する - akiyoko blog
を参考に、Ubuntu に Django アプリを作成します。

$ sudo apt-get update
$ sudo apt-get -y install python-dev git tree
$ sudo apt-get -y install mysql-server
$ sudo apt-get -y install mysql-client libmysqlclient-dev python-mysqldb
$ sudo mysql_install_db
$ sudo vi /etc/mysql/my.cnf
$ sudo service mysql restart
$ sudo mysql_secure_installation
$ mysql -u root -p
mysql> create database myproject character set utf8;
mysql> create user myprojectuser@localhost identified by "myprojectuserpass";
mysql> grant all privileges on myproject.* to myprojectuser@localhost;
mysql> flush privileges;
mysql> exit

$ wget https://bootstrap.pypa.io/get-pip.py
$ sudo -H python get-pip.py
$ sudo -H pip install virtualenv virtualenvwrapper
$ cat << EOF >> ~/.bash_profile

if [ -f ~/.bashrc ]; then
    . ~/.bashrc
fi
EOF
$ cat << EOF >> ~/.bashrc

source /usr/local/bin/virtualenvwrapper.sh
export WORKON_HOME=~/.virtualenvs
EOF
$ source ~/.bashrc
$ mkvirtualenv myproject
$ sudo mkdir -p /opt/webapps/myproject
$ sudo chown -R `whoami`. /opt/webapps
$ pip install MySQL-python
$ cd /opt/webapps/myproject/
$ pip install Django
$ django-admin startproject config .
$ python manage.py startapp blog
$ vi config/settings.py
(INSTALLED_APPS に blog を追加、DATABASES の設定を MySQL に変更)

config/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]
    ・
    ・
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'myprojectuser',
        'PASSWORD': 'myprojectuserpass',
        'HOST': '',
        'POST': '',
    }
}
$ vi blog/models.py
from __future__ import unicode_literals

from django.db import models
from django.utils.translation import ugettext_lazy as _


classBlogPost(models.Model):
    """    A blog post."""classMeta:
        verbose_name = _("Blog post")
        verbose_name_plural = _("Blog posts")

    categories = models.ManyToManyField("BlogCategory", verbose_name=_("Categories"),
                                        blank=True, related_name="blogposts")
    image = models.ForeignKey("BlogImage", verbose_name=_("Featured Image"),
                              related_name="blogposts", blank=True, null=True)
    user = models.ForeignKey("auth.User", verbose_name=_("Author"), related_name="blogposts")
    title = models.CharField(_("Title"), max_length=255)
    content = models.TextField(_("Content"), blank=True)


classBlogCategory(models.Model):
    """    A category for grouping blog posts into a series."""classMeta:
        verbose_name = _("Blog Category")
        verbose_name_plural = _("Blog Categories")

    title = models.CharField(_("Title"), max_length=255)


classBlogImage(models.Model):
    """    A featured image."""classMeta:
        verbose_name = _("Blog Image")
        verbose_name_plural = _("Blog Images")

    caption = models.CharField(_("Caption"), max_length=255)
    image_url = models.FileField(verbose_name=_("Image URL"), max_length=255, blank=True, null=True)
$ python manage.py makemigrations
$ python manage.py migrate


 

検証

まずは事前準備として、初期データを投入します。

$ python manage.py shell
>>> import logging
>>> l = logging.getLogger('django.db.backends')
>>> l.setLevel(logging.DEBUG)
>>> l.addHandler(logging.StreamHandler())

>>> from blog.models import BlogPost, BlogCategory, BlogImage
>>> from django.contrib.auth.models import User

>>> User(username='user-1').save()
>>> BlogCategory(title='cat-1').save()
>>> BlogCategory(title='cat-2').save()
>>> BlogImage(caption='image-1', image_url='blog/image1.jpg').save()
>>> user1 = User.objects.get(pk=1)
>>> cat1 = BlogCategory.objects.get(pk=1)
>>> cat2 = BlogCategory.objects.get(pk=2)
>>> image1 = BlogImage.objects.get(pk=1)
>>> BlogPost(image=image1, user=user1, content='post-1').save()
>>> post1 = BlogPost.objects.get(pk=1)
>>> post1.categories = [cat1, cat2]
>>> BlogPost(user=user1, content='post-2').save()
>>> post2 = BlogPost.objects.get(pk=2)


 
ここからが、本番です。

 

1)多対一、一対一のリレーション先のオブジェクトはフィールドにアクセスした時点でクエリが発行される
>>> post1 = BlogPost.objects.filter(pk=1)[0]
(0.002) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
>>> post1.user
(0.000) SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1; args=(1,)
<User: user-1>
>>> post1.image
(0.001) SELECT `blog_blogimage`.`id`, `blog_blogimage`.`caption`, `blog_blogimage`.`image_url` FROM `blog_blogimage` WHERE `blog_blogimage`.`id` = 1; args=(1,)
<BlogImage: BlogImage object>
1−1)クエリ発行後は取得したオブジェクトがキャッシュされるため、それ以降のクエリは発行されない
>>> post1 = BlogPost.objects.filter(pk=1)[0]
(0.002) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
>>> post1.user
(0.000) SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1; args=(1,)
<User: user-1>
>>> post1.user
<User: user-1>
>>> post1.image
(0.001) SELECT `blog_blogimage`.`id`, `blog_blogimage`.`caption`, `blog_blogimage`.`image_url` FROM `blog_blogimage` WHERE `blog_blogimage`.`id` = 1; args=(1,)
<BlogImage: BlogImage object>
>>> post1.image
<BlogImage: BlogImage object>
1−2)リレーション先のレコードが存在しなくても NotFound は発生しない
>>> post2 = BlogPost.objects.filter(pk=2)[0]
(0.001) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 2 LIMIT 1; args=(2,)
>>> post2.image
>>> post2.image isNoneTrue


 

2)一対多、多対多のリレーション先のオブジェクト群は、all や filter でアクセスする度にクエリが発行される
>>> post1 = BlogPost.objects.filter(pk=1)[0]
>>> post1.categories
<django.db.models.fields.related_descriptors.ManyRelatedManager object at 0x7f2509080a10>
>>> post1.categories.all()
(0.001) SELECT `blog_blogcategory`.`id`, `blog_blogcategory`.`title` FROM `blog_blogcategory` INNER JOIN `blog_blogpost_categories` ON (`blog_blogcategory`.`id` = `blog_blogpost_categories`.`blogcategory_id`) WHERE `blog_blogpost_categories`.`blogpost_id` = 1 LIMIT 21; args=(1,)
[<BlogCategory: BlogCategory object>, <BlogCategory: BlogCategory object>]
>>> post1.categories.all()
(0.000) SELECT `blog_blogcategory`.`id`, `blog_blogcategory`.`title` FROM `blog_blogcategory` INNER JOIN `blog_blogpost_categories` ON (`blog_blogcategory`.`id` = `blog_blogpost_categories`.`blogcategory_id`) WHERE `blog_blogpost_categories`.`blogpost_id` = 1 LIMIT 21; args=(1,)
[<BlogCategory: BlogCategory object>, <BlogCategory: BlogCategory object>]
2−1)リレーション先のレコードが存在しなくても NotFound は発生しない
>>> post2 = BlogPost.objects.filter(pk=2)[0]
(0.001) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 2 LIMIT 1; args=(2,)
>>> post2.categories.all()
(0.001) SELECT `blog_blogcategory`.`id`, `blog_blogcategory`.`title` FROM `blog_blogcategory` INNER JOIN `blog_blogpost_categories` ON (`blog_blogcategory`.`id` = `blog_blogpost_categories`.`blogcategory_id`) WHERE `blog_blogpost_categories`.`blogpost_id` = 2 LIMIT 21; args=(2,)
[]


 

3)select_related を使うことで、一度のクエリで多対一、一対一のリレーション先のオブジェクトを取得してキャッシュしてくれる

なお、

  • null=False(デフォルト) の ForeignKey の場合は INNER JOIN で結合
  • null=True の ForeignKey の場合は LEFT OUTER JOIN で結合

となる。

>>> post1 = BlogPost.objects.filter(pk=1).select_related('user', 'image')[0]
(0.001) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content`, `blog_blogimage`.`id`, `blog_blogimage`.`caption`, `blog_blogimage`.`image_url`, `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `blog_blogpost` LEFT OUTER JOIN `blog_blogimage` ON (`blog_blogpost`.`image_id` = `blog_blogimage`.`id`) INNER JOIN `auth_user` ON (`blog_blogpost`.`user_id` = `auth_user`.`id`) WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
>>> post1.user
<User: user-1>
>>> post1.image
<BlogImage: BlogImage object>


 

4)select_related の引数を指定しない場合は、多対一、一対一になっているリレーション先を全て取得してくれるのではなく、null=False の ForeignKey のみが取得対象

なので、select_related の引数は明示的に指定しましょう。

>>> post1 = BlogPost.objects.filter(pk=1).select_related()[0]
(0.001) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content`, `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `blog_blogpost` INNER JOIN `auth_user` ON (`blog_blogpost`.`user_id` = `auth_user`.`id`) WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
>>> post1.user
<User: user-1>
>>> post1.image
(0.000) SELECT `blog_blogimage`.`id`, `blog_blogimage`.`caption`, `blog_blogimage`.`image_url` FROM `blog_blogimage` WHERE `blog_blogimage`.`id` = 1; args=(1,)
<BlogImage: BlogImage object>


 

5)prefetch_related を使うことで、先行してクエリを発行して、一対一、多対一、一対多、多対多のリレーション先のオブジェクト(群)を取得してキャッシュしてくれる

prefetch_related の場合は、JOIN 句を使うのではなく、クエリを別々に発行して、プログラム的にオブジェクト内に結合してくれます。クエリの総数が減ることはありませんので、クエリの発行数を減らすという目的で prefetch_related を使用することはできません。


(多対一の場合)

>>> post1 = BlogPost.objects.filter(pk=1).prefetch_related('user')[0]
(0.001) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
(0.000) SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` IN (1); args=(1,)
>>> post1.user
<User: user-1>
>>> post1.__dict__
{'user_id': 1L, 'title': u'', '_user_cache': <User: user-1>, '_state': <django.db.models.base.ModelState object at 0x7f2509033310>, 'content': u'post-1', 'image_id': 1L, '_prefetched_objects_cache': {}, 'id': 1L}


(一対多の場合)

>>> user1 = User.objects.filter(pk=1).prefetch_related('blogposts')[0]
(0.001) SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1 LIMIT 1; args=(1,)
(0.000) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`user_id` IN (1); args=(1,)
>>> user1.blogposts.all()
[<BlogPost: BlogPost object>, <BlogPost: BlogPost object>]


(多対多の場合)

>>> post1 = BlogPost.objects.filter(pk=1).prefetch_related('categories')[0]
(0.000) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)
(0.000) SELECT (`blog_blogpost_categories`.`blogpost_id`) AS `_prefetch_related_val_blogpost_id`, `blog_blogcategory`.`id`, `blog_blogcategory`.`title` FROM `blog_blogcategory` INNER JOIN `blog_blogpost_categories` ON (`blog_blogcategory`.`id` = `blog_blogpost_categories`.`blogcategory_id`) WHERE `blog_blogpost_categories`.`blogpost_id` IN (1); args=(1,)
>>> post1.categories.all()
[<BlogCategory: BlogCategory object>, <BlogCategory: BlogCategory object>]
>>> post1.categories.__dict__
{'source_field': <django.db.models.fields.related.ForeignKey: blogpost>, 'reverse': False, 'source_field_name': 'blogpost', '_constructor_args': ((<BlogPost: BlogPost object>,), {}), 'creation_counter': 32, 'target_field_name': u'blogcategory', '_inherited': False, '_db': None, 'query_field_name': u'blogposts', '_hints': {}, 'prefetch_cache_name': 'categories', 'instance': <BlogPost: BlogPost object>, 'through': <class'blog.models.BlogPost_categories'>, 'core_filters': {u'blogposts__id': 1L}, 'symmetrical': False, 'model': <class'blog.models.BlogCategory'>, 'related_val': (1L,), 'target_field': <django.db.models.fields.related.ForeignKey: blogcategory>, 'name': None}


 
なお、filter() ではクエリが再発行されてしまうようです。all() を先取りしてキャッシュしているのかな。。

>>> post1 = BlogPost.objects.filter(pk=1).prefetch_related('categories')[0]
>>> post1.categories.filter()
(0.000) SELECT `blog_blogcategory`.`id`, `blog_blogcategory`.`title` FROM `blog_blogcategory` INNER JOIN `blog_blogpost_categories` ON (`blog_blogcategory`.`id` = `blog_blogpost_categories`.`blogcategory_id`) WHERE `blog_blogpost_categories`.`blogpost_id` = 1 LIMIT 21; args=(1,)
[<BlogCategory: BlogCategory object>, <BlogCategory: BlogCategory object>]


 
あと、prefetch_related の引数を指定しないと、リレーション先を取得してくれないように見えます。どこまでリレーション先を取ってくるか分からないから、明示的に指定しないと取得しないという仕様なのかもしれません。

なので、prefetch_related の引数は明示的に指定しましょう。

>>> post1 = BlogPost.objects.filter(pk=1).prefetch_related()[0]
(0.000) SELECT `blog_blogpost`.`id`, `blog_blogpost`.`image_id`, `blog_blogpost`.`user_id`, `blog_blogpost`.`title`, `blog_blogpost`.`content` FROM `blog_blogpost` WHERE `blog_blogpost`.`id` = 1 LIMIT 1; args=(1,)

 

まとめ

select_related や prefetch_related の使い道としては主に、後続の処理で何度もアクセスされるオブジェクトを先に取得しておきたいときに使うのがよいと思います。特に、一側のオブジェクトを取得する場合でクエリの本数を減らしたいなら select_related を、多側のオブジェクト群を取得したいなら prefetch_related を検討すればよいでしょう。


Django ORM は、クエリ(SQL)をあまり意識せずに使えて便利な半面、何も分からずに使っていると、クエリの本数や実行速度がボトルネックになって、応答速度の遅い処理を作ってしまいがちです。

クエリの実行を含む処理の応答速度が遅い場合は、まずはクエリを確認し、select_related や prefetch_related を使って実行速度を改善することも検討すべきです。

*1:一対一リレーションの挙動は、多対一リレーションの場合とほぼ同じでした。双方から ForeignKey が付与されていると考えればよいのかも。

*2:PyCharm Professional のデータベース機能を使いました。http://akiyoko.hatenablog.jp/entry/2016/03/13/141600を参照

Django ORM の SQL を出力する方法まとめ

$
0
0

Django ORM を使っていると、どういった SQL が発行されているか、クエリの内容を出力したいときが多々あります。

SQL を出力する方法についてはいくつか方法がありますが、今回はその方法を思いつく限りピックアップしてみようと思います。

 

1)QuerySet の query を print する

個人的に一番よく使う方法。
実際に SQL を発行せずに、発行予定の SELECT文を出力することができます。

Django shell だろうが、pdb デバッグ中だろうが、PyCharm のデバッグ中だろうが、いつでも利用することができます。

例えば、Django shell で使う場合はこんな感じ。

$ python manage.py shell
>>> from django.contrib.auth.models import User
>>> print User.objects.filter(pk=1).query
SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1


事前に何も設定しなくても、デバッグ中に手っ取り早く発行された SQL が確認できるのが特徴です。しかしながら、発行された SQL をリアルタイムに確認することはできません。


(参考)Show the sql Django is running? - Stack Overflow


 

2)DefaultConnectionProxy の queries を出力する

直前に発行された SQL を確認することができます。
1)とセットで使うことが多いでしょうか。

$ python manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.filter(pk=1)
[<User: user-1>]
>>> User.objects.filter(pk=2)
[<User: admin>]

>>> from django.db import connection
>>> connection.queries
[{u'time': u'0.000', u'sql': u'SET SQL_AUTO_IS_NULL = 0'}, {u'time': u'0.000', u'sql': u'SET SQL_AUTO_IS_NULL = 0'}, {u'time': u'0.000', u'sql': u'SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1 LIMIT 21'}, {u'time': u'0.001', u'sql': u'SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 2 LIMIT 21'}]
>>> connection.queries[-1]
{u'time': u'0.001', u'sql': u'SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 2 LIMIT 21'}

発行したクエリは、'time'(実行時間)と 'sql'の dict として、発行された順に後ろに追加されていきます。慣れるまで、出力内容が少し読みにくいのが難点でしょうか。

またこちらの方法でも、発行された SQL をリアルタイムに確認することはできません。


(参考)Show the sql Django is running? - Stack Overflow


 

3)django-debug-toolbar の SQL Panel を使う

プラグインのインストールが必要な物の、一番楽チンな方法。

Django を runserver で起動して、実際に画面を操作してから、右側に表示される SQL Panel を開いて確認するだけです。


django-debug-toolbar の SQL Panel を使うには、条件がいくつかあります。

  • DEBUG = True
  • 'django.contrib.staticfiles'が INSTALLED_APPS に設定済み *1

他にも、settings.py に以下の設定が必要です。 *2

INSTALLED_APPS += ('debug_toolbar',)

defalways_show_toolbar(request):
    returnTrue

DEBUG_TOOLBAR_CONFIG = {
    'SHOW_TOOLBAR_CALLBACK': '%s.always_show_toolbar' % __name__,
}


このように、画面からサクサクっと操作が可能です。楽チンですね。

f:id:akiyoko:20160804221039p:plain

f:id:akiyoko:20160804221058p:plain


インストール方法

$ pip install django-debug-toolbar

ちなみに、検証時の環境は以下の通りでした。

  • Python 2.7.6
  • Django (1.9.8)
  • django-debug-toolbar (1.5)


django-debug-toolbar のさらに詳しい説明については、以下の書籍が非常に有用です。「14-04 Django Debug Toolbar」の章に詳しい説明が載っています。
Django 以外にも、Python での開発手法についてのノウハウがいろいろ詰まっていてオススメです。

Pythonプロフェッショナルプログラミング第2版

Pythonプロフェッショナルプログラミング第2版



(参考)


 

4)django-debug-toolbar の debugsqlshell を使う

3)の django-debug-toolbar をインストールしているのであれば、通常の Django shell ではなく debugsqlshell を起動することで、発行される SQL を随時確認することができます。

$ python manage.py debugsqlshell
>>> from django.contrib.auth.models import User
>>> User.objects.filter()

SET SQL_AUTO_IS_NULL = 0 [0.80ms]
SELECT `auth_user`.`id`,
       `auth_user`.`password`,
       `auth_user`.`last_login`,
       `auth_user`.`is_superuser`,
       `auth_user`.`username`,
       `auth_user`.`first_name`,
       `auth_user`.`last_name`,
       `auth_user`.`email`,
       `auth_user`.`is_staff`,
       `auth_user`.`is_active`,
       `auth_user`.`date_joined`
FROM `auth_user` LIMIT 21 [0.19ms]
[<User: admin>]


 

5)django-extensions の shell_plus を --print-sql オプションで起動する

「django-extensions」は、「Django フレームワークの機能を便利に拡張する、管理コマンドやデータベースフィールドなどの詰め合わせ」 *3です。

django-extensions の shell_plus を --print-sql オプションで起動すれば、4)と同じような機能を使うことができます。

$ python manage.py shell_plus --print-sql
>>> from django.contrib.auth.models import User
>>> User.objects.filter()

SET SQL_AUTO_IS_NULL = 0

Execution time: 0.000056s [Database: default]

SELECT `auth_user`.`id`,
       `auth_user`.`password`,
       `auth_user`.`last_login`,
       `auth_user`.`is_superuser`,
       `auth_user`.`username`,
       `auth_user`.`first_name`,
       `auth_user`.`last_name`,
       `auth_user`.`email`,
       `auth_user`.`is_staff`,
       `auth_user`.`is_active`,
       `auth_user`.`date_joined`
FROM `auth_user` LIMIT 21

Execution time: 0.000391s [Database: default]

[<User: admin>]

この shell_plus には autoloading という機能があるらしいのですが、正直なところ使ったことはありません。



インストール方法

$ pip install django-extensions

settings.py に「django_extensions」を追加。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_extensions',
]

(参考)


 

6)django.db.backends のログレベルを動的に変更

事前の準備がほとんど必要なく、1)や 2)のように明示的に SQL を出力する必要がないので、お手軽に使えます。

Django shell で使うケースが多いかもしれません。

$ python manage.py shell
>>>import logging
>>>l = logging.getLogger('django.db.backends')
>>>l.setLevel(logging.DEBUG)
>>>l.addHandler(logging.StreamHandler())

>>> from django.contrib.auth.models import User
>>> User.objects.filter(pk=1)
(0.000) SET SQL_AUTO_IS_NULL = 0; args=None
(0.000) SET SQL_AUTO_IS_NULL = 0; args=None
(0.000) SELECT `auth_user`.`id`, `auth_user`.`password`, `auth_user`.`last_login`, `auth_user`.`is_superuser`, `auth_user`.`username`, `auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`, `auth_user`.`is_staff`, `auth_user`.`is_active`, `auth_user`.`date_joined` FROM `auth_user` WHERE `auth_user`.`id` = 1 LIMIT 21; args=(1,)
[<User: user-1>]


 

7)settings.py の LOGGING を設定

ログに出力したり、コンソールに出力したりと、いろいろ柔軟に設定可能です。リアルタイムに発行される SQL が確認できるのも、この方法の特徴です。

なお、「DEBUG = True」でないと使えないので注意が必要です。


settings.py の設定例

DEBUG = True
LOGGING = {
    'disable_existing_loggers': False,
    'version': 1,
    'handlers': {
        'console': {
            # logging handler that outputs log messages to terminal'class': 'logging.StreamHandler',
            'level': 'DEBUG', # message level to be written to console
        },
    },
    'loggers': {
        '': {
            # this sets root level logger to log debug and higher level# logs to console. All other loggers inherit settings from# root level logger.'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False, # this tells logger to send logging message# to its parent (will send if set to True)
        },
        'django.db': {
            # django also has database level logging'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': False,
        },
    },
}


ただしこの方法だと、ログやコンソールが大量の SQL ですぐに埋め尽くされてしまうので、1)や 2)の方法を使って、確認したい SQL だけをピンポイントに出力するようにした方が開発中は捗るかもしれません。


(参考)django - log all sql queries - Stack Overflow


 

まとめ

今回は、Django ORM の SQL を出力する方法として7種類のやり方を紹介しました。
この中から、目的や状況に応じてやり方を使い分けるようにすると、開発の効率もグンとアップすると思います。

良い Django ライフを!

*1:Django 1.9 では、django-debug-toolbar はデフォルトで INSTALLED_APPS に設定済みです。

*2:ミニマムな設定です。

*3:Pythonプロフェッショナルプログラミング第2版より引用

4/22 の「技術書典4」で「現場で使える 基礎 Django」を頒布します

$
0
0

akiyoko です。

このたび、4/22 の「技術書典4」で人生初の技術系同人誌『現場で使える 基礎 Django』を頒布することになりました。


f:id:akiyoko:20180415003425p:plain:w300
(表紙はこんな感じになりそうです。*1



「技術書典」って何?

技術書典」は、春と秋の年二回ずつ開催される、技術者による技術者のための技術系同人誌の販売イベントです。今回が4回目の開催になりますが、毎回どんどん認知度と熱量が上がっているようで、今回天気が良ければ 3,000〜4,000人ほどの来場者で溢れ返りそうな勢いのホットなイベントなのです(行ったことないけど)。

私は初のサークル参加でもあり、初のイベント参加にもなります。

techbookfest.org

前々から何か本が書きたいなと思っていたところで「当選したら書いてみようかな」という軽いノリでこのイベントのサークル参加に申し込みをしたら、見事に抽選に当たっ(ってしまっ)たのが二月初旬。そこからちまちまと目次を作り始め、本格的に書き始めたのは二月下旬あたり。そこから泣きそうになりながら毎日明け方まで執筆することを繰り返し、ようやく脱稿できそうな目処がついて安堵感を感じ始めています。これまでに要した総時間はおそらく 300時間を超えると思います。



こちらは昨日 Twitter で聞いたアンケート。
半数が入稿済みだった。皆さん早い!!



「基礎 Django」はどんな内容?

全148ページ(表紙や奥付を除けば本文 142ページ)まるまる Django 本です。執筆はほぼ完了し、現在絶賛校正中です。


本書の読者としては、

  • Python の文法はある程度分かるけど Django は初めてという初心者の方
  • Django を始めてみたけど今いちコツが掴めないという初級者の方
  • ベストプラクティスを学びたいと考えている中級者の方

を想定しています。

私自身 Django 歴がまだまだ浅い(仕事で6年ほど)ので上級者向けの本は書けませんが、Django の動作原理から実戦的な書き方まで、初級者向けの基礎知識として押さえるべき内容は全て網羅したつもりです。読者の皆さんに「Django って意外と簡単だな」と感じていただけることを目指して、基礎から詳しく丁寧に解説しています。

特に、

  • Django の日本語書籍が無くて困っている方
  • Django で一度挫折したことがある方

にオススメです。


目次

気になる目次は、



f:id:akiyoko:20180414162745p:plain:w190

f:id:akiyoko:20180414162756p:plain:w190

f:id:akiyoko:20180414162807p:plain:w190


となる予定です。
もう動かない・・・はず。


「基礎 Django」を書いた理由は?

今回 Django 本を書いた理由はズバリ、「Django の日本語の書籍が少ない」からです。私自身、Django をずっと仕事で使っているのですが、日本語で書かれた良書が見つからず、結局「Two Scoops of Django」シリーズという海外の書籍(個人的に「ベスト・オブ・Django本」に認定)に辿り着いたわけですが、それだと初心者向けに薦める本としてはハードルが高過ぎるのではないかとモヤモヤを感じていたのです。Django の人気が今ひとつ上がらないのも、日本語の書籍が不足していることが大きな要因になっているのではないか、と思い立ったのがきっかけです。


akiyoko.hatenablog.jp


この状況を打破すべく、「無いのなら 自分で書こう Django本」ということでまず私から書いてみることにしてみました。この本が版を重ね、将来「ベスト・オブ・Django本」と呼ばれるようになればという願いを込めて。




頒布本情報

B5サイズ、148ページ(1円玉より少し小さい 9.3 mm の厚さです!)。

技術書典での価格は 1,000円。
お釣りの煩雑さを考えての特別価格です(他のサークルさんもだいたい 1,000円にしているようです)。

部数は未定。

頒布場所は「く33」の「あきよこブログ」です。
見本誌を置いてますので、立ち読みだけでもお気軽にどうぞ。

f:id:akiyoko:20180415000417p:plain


秋葉原UDX、4/22(日) 11時オープンですが、午前中はどえらい混雑すると思いますのでご注意を。


今悩んでいること

来週月曜(4/16)が入稿の〆切で、そこで何部刷るかを決めなくてはいけません。

これまでの技術書典の売れ行きから考えて、200部くらい刷れば十分余るかな?と考えていたのですが、「万万が一早々に売り切れてしまって、欲しいという人が買えなかったら嫌だなぁ」という邪念がムクムクと出てきてしまっている状態がまさに今なのです。


後日、BOOTHで当日売り切れなかった紙の本(電子版はもし対応可能であれば)の販売をしようと考えているので、結構余ってもいいとは考えています。


もし反響があれば少し多めに刷ろうかなとも目論んでいたりしますが、どうなることやら。


何はともあれ、技術書典の当日(4/22)、秋葉原 UDX アキバ・スクエア まで遊びに来ていただければありがたいです!

ぜひ冷やかしにきてくださいませ。

*1:黄色の丸は「Django(ダンゴ)三兄弟」です。だいぶ古いな。。

「現場で使える 基礎 Django」ってどんな本? その読みどころをガッチリ解説

$
0
0

akiyoko です。

今回は、4月22日の「技術書典4」 *1で頒布した人生初の技術同人誌 『現場で使える 基礎 Django』の概要と読みどころについて解説します。


現在、オンラインショップの「BOOTH」にて、増刷した紙の本を販売中です。*2 興味を持たれた方は、部数限定・売り切れ御免(再販予定なし)ですので、在庫があるうちにお買い求めいただければと思います。

booth.pm

ショップ側には入庫が完了している状態なので、すでに購入済みの方にはショップ側の検品が終わり次第、順次発送される予定です。



 

概要

どんな本?

この本は、B5サイズ・148ページの 本格的な Django 解説書です。

Django を仕事の現場で6年ほど使っている私が、日本語で書かれた書籍が少なくてずっと困っていたので自ら書きました。「現場でこんな本があったらなぁ」という想いで書いたので、仕事で使っているあなたにぴったりな本に仕上がっているはずです。


表紙はこんな感じです。
電車の中でも読めるようなものがよいと思い、派手さは極力抑えるようにしました。

f:id:akiyoko:20180531233638p:plain:w200


いわゆる「技術系同人誌」というジャンルの自費出版本になりますが、いたって真面目な技術解説書です。

表紙も含めて基本的に一人で作り上げました。レビューには Django 界隈から有志の方二人と、同僚二人に協力していただきました。スタートから入稿まで二ヶ月ほどで書きましたが、執筆にかかった時間は優に300時間を超えていると思います *3


 

内容は?

目次はこのようになっています(クリックで拡大します)。



f:id:akiyoko:20180416234902p:plain:w160

f:id:akiyoko:20180416234958p:plain:w160

f:id:akiyoko:20180416235011p:plain:w160


この本は、サンプルプロジェクトを実装ながら(読者によっては実際に手を動かしながら)技術要素を順番に説明していくような、いわゆるチュートリアル本ではありません。Django の全体像から構成要素の詳細まで、基本動作やハマりやすいポイントについて幅広く解説した本です。読者の方々に「Django って意外と簡単だな」と感じていただけることを目指して、基礎から詳しく丁寧に解説しています。


本書の構成としては、第 3 章までで Django の全体像や重要な概念の説明をおこない、 第 4 章以降でそれぞれの構成要素の説明をしながら、私の知見や経験から得たベストプ ラクティスについても紹介しています。


f:id:akiyoko:20180526163355p:plain:w250


対象読者

本書の対象読者としては、

  • Python の文法はある程度分かるけど Django は初めてという初心者の方
  • Django を始めてみたけど今いちコツが掴めないという初級者の方
  • Django のベストプラクティスを学びたいと考えている中級者の方

を想定しています。特に、

  • Django の日本語書籍が無くて困っている方
  • Django で一度挫折したことがある方

にピッタリな再入門書にもなっていると思います。
しかしながら、Webアプリケーション開発の経験がまるっきり無いという方には多少難しい内容になっているかもしれません。

 

本の評判

日本語のまとまった情報が少ないということでやはりニーズが高かったのでしょうか、技術書典4 では(強気で刷った)300部が3時間ほどで完売してしまいました。当日は初参加の上に予想をはるかに超えた売れ行きにてんてこ舞いで、全く余裕がありませんでした。



Twitter に上がっていた Django 本の感想を勝手にピックアップさせていただきました。おおむね好評のようで、ほっとしました。



本を買っていただいた上に感想までブログに書いてくださった心優しい方も何人かいらっしゃいました。本当にありがとうございます。こちらも勝手に貼り付けさせていただきます。



匿名の読後アンケートフォームを用意して感想を聞かせていただいたのですが(現在も絶賛募集しているので是非とも感想をお願いします)、その結果もおおむね良かったようです。改善すべき点としてご指摘いただいた部分については(すでに v 1.0.1 で対応したものもありますが)今後の改訂や補足ブログのネタにさせていただきたいと思います。



 

読みどころ

章ごとの簡単な解説をしながら、本書の読みどころについて書いていきます。

第1章: はじめに

1.1  なぜ今 Django なのか?
1.2  本書について
1.3  動作環境と各種バージョン
1.4  まとめ

短く書きたかったのですが、勢い余って長くなってしまった序章。

機械学習などで Python を使う人が増えているので、Django もどんどん盛り上がってくるよねという書き出しだったのですが、実際、私がよく参加させていただいている fin-pyでも「Django の勉強がしたい」という声がちらほら聞こえていましたし、最近では日本では初めての DjangoCongressが今年5月に開催されるなど、本格的な盛り上がりを感じます。


Django に少し詳しい人なら気になるのが、Django のバージョンでしょう。結論から言えば、仕事で使うなら今はまだ「1.11 LTS」、趣味で使うなら「2系」を使えばよいと考えています。この本では仕事の現場にフォーカスしたので「1.11」推しとなっていますが、実際には 1.11 と 2.0 はそんなに違いがありません(Python 2 のサポートが切られたことを除いて)。これについては追々、補足のブロク記事で解説したいと思います。

Python は 3.5系で動作確認しましたが、これは 3.6系でも特に問題ないはずです。改訂するのであれば、3.6系を前提に書きたいと考えています。

第2章: アーキテクチャ

2.1  全体像
2.2  MTVフレームワークとは?
2.3  まとめ

何事にもまずは全体像から掴んだ方が理解しやすいので、大枠から解説。ビューやフォーム、モデルなどの構成要素(コンポーネント)がどのように連携しながら動作しているのかを、図を見ながらざっくりと理解することができます。

第3章: プロジェクト構成

3.1  プロジェクトとアプリケーション
3.2  django-admin.py と manage.py
3.3  よくあるプロジェクト構成
3.4  ベストプラクティス1: 分かりやすいプロジェクト構成
3.5  まとめ

本章の読みどころは、startproject コマンドや startapp コマンドを使って自動生成されたファイルの説明と、分かりやすいプロジェクト構成についてです。 *4

第4章: URL ディスパッチャと URLconf

4.1  概要
4.2  URLconfの書き方
4.3  ベストプラクティス2: アプリケーションごとに urls.py を配置する
4.4  まとめ

リクエストをビュー関数に振り分ける「URLディスパッチャ」と、リクエスト URLとビュー関数をマッピングしている「URLconf」(URL設定)についての解説です。URLconf については 2系で書き方が新しくなる(ただし 1系の書き方も継続して使える)ので、そちらは補足ブログで追記したいと考えています。

第5章: ビュー(View)

5.1  概要
5.2  ビュー関数の書き方(関数ベース vs クラスベース)
5.3  全ての基本となる基本汎用ビュー
5.4  シンプルでよく使う基本汎用ビュー
5.5  さまざまな用途に特化した汎用ビュー
5.6  ログイン・ログアウトについて
5.7  まとめ

本書では、関数ベースのビューについてはほとんど説明しておらず、クラスベースビューを中心に解説しています。クラスベースビューを使う理由やメリットについてももちろん書いていますし、デメリットである継承の複雑さやオーバーライドできるメソッドや変数がどうなっているかについては、解決のヒントを提示しています。

この章に書いた、Django でのログイン・ログアウト処理は実はややこしいのですが、よく分かっていなかった人もこれを読めばだいぶスッキリすると思います。

第6章: モデル(Model)

6.1  概要
6.2  モデルクラスの書き方
6.3  「一対一」「多対一」「多対多」リレーションはどう定義するか?
6.4  よく使われるUserモデル
6.5  モデルマネージャとクエリセット
6.6  単体のオブジェクトを取得する
6.7  複数のオブジェクトを取得する
6.8  単体のオブジェクトを保存・更新・削除する
6.9  ベストプラクティス3: Userモデルを拡張する
6.10  ベストプラクティス4: 発行されるクエリを確認する
6.11  ベストプラクティス5: select_related / prefetch_related でクエリ本数を減らす
6.12  まとめ

便利だけど実はいろいろとややこしい、そんなモデルを分かりやすく解説しています。

この章は本書で最もページ数を割いたトピックですが、なぜそんなにページ数を割いたかというと、個人的にモデルが Django 最強の武器(そして最も厄介な諸刃の剣)だと考えているからです。Django を使う場合は DB を使わないことは少ないと思いますので、モデルの仕組みを理解するのは必須でしょう。

モデルの設計で重要な「一対一」「多対一」「多対多」のリレーションについては、基本から説明しています。分かりにくいモデルマネージャとクエリセット、遅延評価、関連先モデルの JOIN についても詳しく説明しています。発展編として、あまり知られていない(と思われる)「select_related」「prefetch_related」の使いどころや実際に発行される SQL 文を確認する方法についても解説しています。

またこの章では、Django の User モデルについても解説。ややこしい継承関係や User モデルのカスタマイズ方法についても取り上げています。

第7章: テンプレート(Template)

7.1  概要
7.2  変数表示
7.3  フィルタ
7.4  テンプレートタグ
7.5  ベストプラクティス6: ベーステンプレートを用意する
7.6  まとめ

Django がデフォルトのテンプレートエンジンとして利用している「DTL(Django Template Language)」の記法について解説(Jinja2 については解説していません)。数あるフィルタやテンプレートタグの中からよく使うものをピックアップして紹介しています。

第8章: フォーム(Form)

8.1  概要
8.2  バリデーションの仕組み
8.3  フォームクラスの書き方
8.4  ビューやテンプレートからフォームを利用する方法
8.5  CSRF対策について
8.6  ベストプラクティス7: こんなときは ModelForm を継承しよう
8.7  まとめ

ユーザーの入力データを保持するためのフォームですが、やはりキモとなるのはバリデーションですよね。フォームでは is_valid() を起点としてさまざまなメソッドが順番に呼ばれますが、そのややこしいバリデーションのフローを図を使って分かりやすく解説しています。また、さらにややこしい ModelForm についても何とか一枚の図にまとめてみました。必見です。

エラーに悩まされた方も多いであろう、CSRF対策(csrf_token)についてもこの章で解説しています。

第9章: ミドルウェア(Middleware)

9.1  概要
9.2  主なミドルウェアの役割
9.3  ミドルウェアの書き方
9.4  ベストプラクティス8: メッセージフレームワークを使う
9.5  まとめ

Django のミドルウェア、何となく使ってませんか?

見逃されがちなミドルウェアですが、実は縁の下の力持ちなんですよね。ということで、新規プロジェクト作成時にデフォルトで設定されるミドルウェアの役割や必要性などについて解説しています。

また、便利なメッセージフレームワーク(いわゆるフラッシュメッセージ)については、注意点やちょっとした TIPS とともにベストプラクティスとして解説しています。

あと、1.11 から導入された ミドルウェアの新しい書き方についても言及しています。django.utils.deprecation.MiddlewareMixin を継承する書き方は非推奨にマークされているので、要注意です。

ミドルウェアについてここまできちんと書いている Django の書籍は、おそらくこれまで無かったと思います。

第10章: 設定オブジェクトと設定ファイル(settings.py)

10.1  概要
10.2  インストールするアプリケーション一覧
10.3  デバッグ設定
10.4  静的ファイルパス関連の設定
10.5  ロギングの設定
10.6  その他の重要な設定
10.7  ベストプラクティス9: 個人の開発環境の設定は local_settings.py に書く
10.8  ベストプラクティス10: シークレットな変数は .env ファイルに書く
10.9  まとめ

実はこの章が本書の一番のウリかもしれません。匿名の読後アンケートでも最も評価が高かった章の一つでもあります。

Django でつまづくパターンとして、settings.py によく分からない設定がたくさん羅列してあるのを見たり、runserver を動かしたときに何だか分からないエラーが出たりして途方に暮れる、というのがあるのではないでしょうか。あるいは、「この設定って何が正解?」「動いたけどこのままでいいんだろうか?」と悩みながら何となく使っているのではないでしょうか。

また、

  • 「INSTALLED_APPS」にはアプリケーション名を書くべきか、それとも apps.py の AppConfig のサブクラスを書くべき?
  • 静的ファイルパス関連の「STATIC_URL」「STATIC_ROOT」「STATICFILES_DIR」の違いは一体何なの?
  • 「SECRET_KEY」や「ALLOWED_HOSTS」って何に使うの?
  • 「LOGGING」は具体的にどう設定すればいいの?

など疑問は尽きないと思います。この章ではこれらの疑問に全てお答えしています。

そして現場で利用するなら必須のベストプラクティスとして、本番用の settings.py と個人開発用のものを分けるための方法や、シークレットな変数値を環境変数に分離する方法などについても解説しています。

第11章: データベースのマイグレーション

11.1  概要
11.2  マイグレーションコマンドについて
11.3  まとめ

マイグレーションについての説明は短め。実際の運用ではもう少しディープな理解が必要かもしれませんが、紙面の都合で割愛しました。

第12章: 開発用 Web サーバ(runserver)を起動する

12.1  概要
12.2  runserver コマンドについて
12.3  まとめ

開発用の Web サーバ(runserver)の特徴や使い方、Docker で利用する場合の注意点について書きました。こちらも割とシンプルにまとめています。

第13章: 管理サイト(Django Admin)

13.1  概要
13.2  モデルの登録方法
13.3  一部機能のカスタマイズ方法
13.4  利用条件
13.5  使い方
13.6  まとめ

Django の便利な点として、この管理サイト(Django Admin)が挙げられるかと思います。ログインできるユーザーや権限などの利用条件、一部機能のカスタマイズ方法など、少し詳しめに解説しています。

第14章: 便利な Django パッケージを使おう

14.1  概要
14.2  DRY系パッケージ
14.3  開発補助系パッケージ
14.4  まとめ

実際に開発する際にほぼ必須の知識になってくる「Django パッケージ」について、選定のコツや私のオススメするパッケージをいくつか紹介しています。

第15章: サンプル実装

「本のオンラインショップ」をテーマに、ログイン・ログアウトまわりを中心に実装したサンプルプロジェクトです。本書で説明したことをベースにしたサンプル実装になっており、コードには日本語の説明をなるべく多く書きました。紙面の都合でコードの掲載はカットし、その代わりにソースコードのURLを載せています。

付録

付録A: macOS における Django 開発環境の構築方法
付録B: Docker でラクラク開発
付録C: 覚えておきたい Django 管理コマンド 10 選

ローカルPC への Python の導入方法については、技術書典バージョンでは Anaconda を使った方法について書いていましたが、読者の方からの指摘を受けて、「v1.0.1」(BOOTH での6月以降販売分)ではよりシンプルな方法に修正しています。また、Django の開発環境についても PyCharm をベースにしたものに書き直しました。

あと、自分でも最近取り入れて良かったと思っているのが「Docker でラクラク開発」です。ローカルPCの環境を汚すことがなく、要らなくなったらすぐに環境を作り直せるので、開発や検証が容易になります。



 

おわりに

「現場で使える 基礎 Django」ってどういう本なの? 買うべきなの? と悩んでいる人向けに、この本はどういう本なのか、誰にピッタリな本なのかを解説してみました。

仕事の現場で使っている人を主なターゲットにしていますが、仕事ではなく趣味で使ってるという方や、2系の情報が知りたいという方にも有益な情報がたくさん含まれているはずですので、是非ともお手にとっていただければと思います。よろしくお願いします。


《販売サイトはこちら》
booth.pm


おまけ

DjangoCongressJP 2018 の一日目に一般参加したのですが、偶然にも LT で発表させていただく機会を得て、「Django の同人誌を書いた話」というテーマで登壇しました。

意外と小心者なので、テンパって噛みまくりでお聞き苦しかったかと思います。その節は大変失礼いたしました。

*1:春と秋の年二回ずつ開催される、技術者による技術者のための技術系同人誌の販売イベント。今回は4回目の実施となり、参加者は6,000人を超えました。 https://techbookfest.org/event/tbf04

*2:技術書典4で頒布したものから少しだけ改訂した「v1.0.1」バージョンになります。ページ数は同じです。

*3:多忙な時期とも重なり、本当に死ぬほど疲れました。。

*4:しかしながら、これがベストか?については異論あると思います。もう少し複雑になった場合の本格的なプロジェクト構成について、もし続編を書くのであればこのあたりも補足してみたいと考えています。

Django 1.11 と 2.0 の違い (「現場で使える 基礎 Django」本の補講その1)

$
0
0

akiyoko です。
この記事では、私が執筆した Django の同人誌「現場で使える 基礎 Django」で説明しきれなかった部分の加筆・補足をします。まだ本を読んでいない方にも読める記事になっていると思いますので、ご安心を。

今回は、「Django のバージョン」、とりわけ「Django 1.11 と 2.0 の違い」について取り上げます。


「現場で使える 基礎 Django」の表紙に書かれた 「1.11 LTS 対応」という文字を見て、「なーんだ、最新の Django 2 じゃないのかよ!」と敬遠している貴方のためにせっせと書き上げました。


《宣伝》

「現場で使える 基礎 Django」は現在、増刷して絶賛発売中です!
booth.pm




Django のバージョンについて

昨年2017年12月に、Django 2.0 がリリースされました。
Wikipediaによると 1.0 がリリースされたのが2008年9月なので、実に9年3ヶ月ぶりのメジャーバージョンアップとなりました。


それから半年ほど経ちましたが、現場ではまだ1系と2系が混在している、いわば過渡期の状況ではないでしょうか(あくまで私の肌感覚ですが)。


理由は3つほど考えられます。

【理由その1】

まずは、LTS の問題です。LTS とは「Long-Term Support」の略で、開発コミュニティからセキュリティパッチが長期間提供される特別なバージョンのことを指します。その点、Django 2系はまだ LTS バージョンがリリースされていません。LTS として予定されている「2.2」のリリースは 2019年4月となっており、まだ 10ヶ月ほど先になっているのが、2系へのバージョンアップに踏み切れない理由の一つに挙げられます。

f:id:akiyoko:20180531235800p:plain:w500
Django のバージョンごとのサポート状況
(画像は https://www.djangoproject.com/download/より引用)


すでに次期 LTS の「2.2」のロードマップも細かく決まっていて(多少ずれるようですが)、2019年の4月にリリースされることが予定されています。

予定日詳細
2019年1月14日Django 2.2 アルファ版; 追加機能凍結
2月15日Django 2.2 ベータ版; バグフィックス凍結(致命的なバグ対応は除く)
3月15日Django 2.2 RC 1(リリース候補); 翻訳凍結
4月1日までDjango 2.2 正式版

https://code.djangoproject.com/wiki/Version2.2Roadmapより)


なお、1系のマイナーバージョン「1.12」はリリースされないことが決まっているため、「1.11」が 1系で最後のマイナーバージョンとなります。1系の最新バージョンは本記事の執筆時点で「1.11.14」となっています。


ということで、ビジネスで利用するとなると公式サポートが長い 1系がまだまだ主役の場合が多いのではないでしょうか。実際、現場の動きとしては「早く 2系へ移行しなければ!」という切迫感はまだあまり感じられません。

【理由その2】

次に、「Django 2系が Python 2のサポートを打ち切った」というのも、Django 2 への移行を阻害している大きな要因になっているのではないかと考えています。例えば、Python 2 で実稼働している Django 1系のプロジェクトでは、直ちに 2系にバージョンアップできない事情もあるでしょう。

【理由その3】

最後に、状況によっては利用しているライブラリが Django 2 にまだ対応していないということも考えられます。


結論として、現時点では、仕事の現場で使うなら「1.11 LTS」(2.2 LTS に向けて 2.0 から追従していくなら 2系でもOK)、趣味や研究で利用するなら「2系」を使えばよいと私は考えます。





ここで、実際の Django のバージョン別の利用状況を見てみましょう。

5月に開催された DjangoCongress JP 2018で発表された事前アンケートの結果によると、Django 各バージョンの利用状況は以下の通りでした。


f:id:akiyoko:20180530221907p:plain:w300
DjangoCongress JP 2018 事前アンケート画像を akiyoko が編集)

Django バージョン利用率
1.8 以前約 12 %
1.8 LTS約 20 %
1.9〜1.10約 21 %
1.11 LTS約 24~25 %
2.0約 22~23 %


2.0 の利用率が22~23 %にとどまっているという結果は要注目です。私の率直な感想は「意外と少ないなぁ」でした。半分まではいかないとしても、もう少し多いのかなと予想していました。もちろんアンケート自体は何ヶ月か前から収集していたはずなので、現時点での数値とは多少の開きがあるとは思いますが。


Django 1.11 と 2.0 の変更点

Django 2.0 のリリースノートには、1系の最終バージョンである「1.11」から「2.0」への変更点が記載されています。


大きな変更点としては、

  • Python 2 のサポートが打ち切られた
  • URLconf の書き方が簡単になった(django.urls.path() が追加)
  • モデルの ForeignKey と OneToOneField で「on_delete」オプションが必須に

が挙げられるでしょうか。後で詳しく説明します。

それ以外の細かな変更点のうち個人的に気になったところを以下にズラズラと挙げましたが、ぶっちゃけ、そこまで大きな変更点はありません。一番インパクトが大きいのはやはり、上で挙げた 「Python 2 のサポート打ち切り」でしょう。

  • ミドルウェアを settings.py で設定する際の変数「MIDDLEWARE_CLASSES」が廃止(「MIDDLEWARE」を使う)
  • User.is_authenticated() と User.is_anonymous() がメソッドではなく、属性になった
  • 管理サイトの画面がレスポンシブ対応に
  • Window 関数の OVER 句に対応
    • MySQL では 8.0.2 以降で対応
  • MySQL でクエリ内の「__search」ルックアップが使えなくなった
  • MySQL のトランザクション分離レベル(isolation level)のデフォルトが「read committed」に。1系では「repeatable read」だった
  • runserver で立ち上がるサーバが HTTP/1.1 に対応
  • django.conf.urls.include() の namespace を指定するときは、インクルード先の URLconf に app_name の指定が必須になった
    • app_name が指定されてあって、且つ namespace を include の引数として指定すると、値を上書きできるっぽい
  • django.conf.urls.include() の app_name 引数がなくなった
  • カスタムテンプレートタグがキーワード引数のみを許容
  • handler404 などのハンドラがコーラブルに(1系ではドット区切りの文字列だった)
  • バイト文字列はインプット・アウトプット以外の部分では扱わないようになった *1
  • AbstractUser.last_name の max_length が 150 に増えた(これまでは 30)
  • クエリをスライシングした後に QuerySet.reverse() や last() ができなくなった
  • 外部キー制約が SQLite でも有効に
  • QuerySet.iterator() が一度に取得する行数が 100 から 2000 になった

ここに挙げたものの中には検証していないものも多々ありますので、誤訳や誤解がありましたらご指摘いただけるとありがたいです。




大きな変更点として挙げた3点について、詳しく説明していきます。

1. Python 2 のサポート打ち切り

先に述べた通り、Django 2.0 では Python 2系のサポートが打ち切られました。Django 2 を使う場合には、Python 3.4 以降が最低限必要になります。Django 1.11 および 2.0 がサポートする Python のバージョンをまとめたものが以下の表になります。

 Python 2.73.43.53.6
Django 1.11
Django 2.0


(Python 2 系をサポートする最後のバージョンである)Django 1.11 LTS のサポートは早ければ 2020年4月に終了、Python 2.7 自体のバグフィックスのサポートは2020年1月に終了するので、Python 2 を使っているプロジェクトは2019年末までには3系への移行を済ませる必要があります。

Python 2 で苦労した私としては、Python 2 のサポートをバッサリ切ったことはかなり嬉しいのですが、対応に追われるプロジェクトも今後出てきて大変そうだなという印象です。 *2


2. URLconf の書き方(URL ルーティングのシンタックス)

Django 1系では、正規表現の URL ルーティングは django.conf.urls.url() 関数を使って

from django.conf.urls import url

...(略)...
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^shop/(?P<book_id>\d+)/$', views.detail, name='shop_detail'),

というシンタックスで書いていましたが、新しく追加された django.urls.path() 関数を使って

from django.urls import path

...(略)...
path('articles/<int:year>/', views.year_archive),
path('shop/<int:book_id>/', views.detail, name='shop_detail'),

と簡潔に書くことができるようになりました。
django.conf.urls.url() を使った書き方は、Django 2.0 でもそのまま使えるように互換性が保たれていますし、同じ用法で使える django.urls.re_path() が追加されたのでそれを使って書き直してもよいと思います。

3. ForeignKey と OneToOneField で「on_delete」オプションが必須に

モデルの ForeignKey と OneToOneField で「on_delete」フィールドオプションが必須になりました。このあたりは、「現場で使える 基礎 Django」の中でもしっかり説明してあります。


booth.pm



ここで、細かな変更点のうち、Windows 関数のサポートについても少し説明を加えておきます。

Window 関数について

Windows 関数は、あるまとまったデータ群(Window で区切られた集合)に対して集計処理をするための機能です。ランク付け(RANK 関数を使う)が一番理解しやすいでしょうか。なお、全ての Window 関数には「OVER句」が必要になります。

(参考)[SQL] 最強の分析ツールと言われるWindow関数について私が学んだこと | Developers.IO


Window 関数自体は、PostgreSQL や Oracle では以前からサポートされていましたが、MySQL では 8.0.2 以降で導入されています。なお、Django 組み込みのバックエンドも PostgreSQL、Oracle、MySQL(8.0.2以降)で Window関数をサポートしていますが、データベースの種類と関数によってはサポートが異なる場合もあるとのことです。 *3




最後に、MySQL のトランザクション分離レベルについて調べたことを書いておきます。

MySQL のトランザクション分離レベルについて

tree-tips: MySQLのトランザクション分離レベル | MySQL」に簡潔にまとめられていたのですが、1系でデフォルトだった「repeatable read」は 2系でデフォルトになる「read committed」に比べて「ファジーリード」(他セッションがコミットした更新データを参照してしまう)や「ファントムリード」(他セッションがコミットした追加データを参照してしまう)は起きないが、性能は「read committed」の方がよい(バージョン管理の範囲が狭くなるため)とされています。

MySQL 自体のデフォルトの分離レベルは MySQL5.6の公式ドキュメントによると「repeatable read」で、8.0 でも変わりません(変わるという噂もあるようですが)。それに対して、Oracle、PostgreSQL、SQL Server などでは「read committed」がデフォルトとなっています。

(参考)

 

そもそも 2.0 へのバージョンアップは必要なのか?

さて、そもそも 2.0 へのバージョンアップは必要なのでしょうか?


パッケージをアップデートする理由は、

  • 新しいバージョンで導入された新しい機能や改善点を利用したい場合
  • バグ修正によるリスク減少
  • セキュリティパッチのサポート延長
  • 一気にバージョンアップすることのコストを抑える
    • 例えば、LTS から LTS への大ジャンプはコストが掛かるため、普段から出来るかぎり最新バージョンに追随しておく
  • 依存しているパッケージ・言語のサポートの問題

などが考えられます。 *4


しかしながら、これらのメリットが無いのであれば、現在使っているパッケージを無理にバージョンアップさせなくてもよいでしょう。バージョンアップしなくても、例えば、特定箇所のバグ修正であれば手動でバックポートすることで対応できることもあります。


最後に

最後に一番大事な話。
4月に「技術書典4」で販売して即完売した「現場で使える 基礎 Django」が、現在増刷して絶賛発売中です!

対象バージョンは「Django 1.11 LTS」となっていますが、この記事で説明したように、Django の「1.11 LTS」と「2.0」は(Python 2 のサポート以外は)それほど大きな変更点はなく、「2.2 LTS」がまだリリースしていないため様子見が必要ということを踏まえると、もう買うしかないという気持ちになってきたはずですよね。

booth.pm


この本は B5サイズ・148ページの 本格的な Django 解説書 ですが、Django を仕事の現場で6年ほど使っている私が 「現場でこんな本があったらなぁ」という想いで書いたので、仕事で使っているあなたにぴったりな本に仕上がっているはずです。
そしてこの本は特に、

  • Django の日本語書籍が無くて困っている方
  • Django で一度挫折したことがある方

に絶対オススメの一冊となっています。


過去記事で読みどころの解説や読者の方々の評価を紹介していますので、気になる方はこちらも合わせてご覧ください。

《過去記事》
akiyoko.hatenablog.jp


*1:困っている人は「Django 2.0へのアップデート (Removed support for bytestrings編)」の記事が参考になるはず!

*2:他人事ではないのが恐ろしいところ。。

*3:Query Expressions | Django documentation | Django

*4:Upgrading Django to a newer version | Django documentation | Djangoを参考


無料版 PyCharm で Django 開発環境を構築するまでの手順(「現場で使える 基礎 Django」本の補講その2)

$
0
0

akiyoko です。
この記事では、私が執筆した Django の同人誌「現場で使える 基礎 Django」で説明しきれなかった部分の加筆・補足をしています。まだ本を読んでいない方にも読める記事になっていますので、ご安心を。

補講その2として今回は、「無料版 PyCharm で Django 開発環境を構築するまでの手順」について取り上げます。


記事の前半で「PyCharm」の概要や利点、「Professional 版」と「Community 版」(「CE」と略されます)のエディションの違い、Professinal 版のライセンスと料金体系を説明し、後半で無料版の「PyCharm CE」を使って Django の開発環境を構築するまでの手順を解説します。


同人誌を購入済みの方のために補足すると、技術書典4 で頒布したバージョン(v1.0.0)の「付録A:macOS の Python 3 環境構築の方法」や 6月以降に再販したバージョン(v1.0.1)の「付録A:macOS における Django 開発環境の構築手順」とは若干手順が異なっていますので、すでにお読みの方はご注意ください。改訂箇所は以下の通りです。

  • (使う必然性がなかったので)Anaconda を使わないように改訂(v1.0.1)
  • 初心者でも簡単に環境構築できるように PyCharm CE を使うやり方に改訂(v1.0.1)
  • 説明を簡便にするために、Python をインストールするまでの手順を省略(本記事)
  • インストールする Python のバージョンを 3.5.2 → 3.6.5 に変更(本記事)

本ブログ記事では長々と書いていますが、同人誌ではスッキリと書いていますのでご安心ください。



《CMコーナー》
「現場で使える 基礎 Django」は現在、増刷して絶賛発売中です!
booth.pm





PyCharm とは

PyCharm」は「統合開発環境」(IDE)と呼ばれる開発ツールで、Python で開発をする際にいろいろと便利な機能を利用することができます。仕事の現場でメモ帳を使って開発するとあまりにも非効率なので、このようなツールが一般的に使われています。

JetBrains社の IDE では Java 向けの「IntelliJ IDEA」や、PHP 向けの「PhpStorm」が有名ですが、Python 向けの IDE が「PyCharm」という位置付けになっています。私は、Python 開発にはもっぱらこの「PyCharm」を愛用しています。

メリットとデメリット

私が Python の開発に PyCharm を使う理由は、以下の点が気に入っているからです。

  • コードジャンプ機能と自動整形機能を使うことで開発効率が著しく向上する
  • インストールしたそのままの状態で快適に使える

その他にも以下のようなメリットがあり、Python があまり得意でない方にも便利に使うことができるのも魅力です。

  • venv」(仮想環境を作成するためのモジュール)や「pip」(パッケージ管理ツール)のコマンドの使い方が分からなくても、PyCharm の画面からポチポチと操作できる
  • Windows 版も Mac 版もだいたい同じ操作性や見た目になるのでナレッジが共有しやすい

現時点でのデメリットとしては、例えば以下のものが挙げられるかと思います。

  • 一部機能が有料の Professional 版でないと使えない(後述します)
  • 現時点で Pipenvに未対応 *1
  • conda を使っている場合に PyCharm の画面からパッケージがインストールできない不具合がある(?)


PyCharm 関連でよく話題に上がるのが、エディションとライセンス、そして料金体系です。

エディション(Professional 版と Community 版の違い)

PyCharm には有料の「Professional」版と無料の「Community」版(CE)とがあり、Community 版では一部機能が使えないといった制限があります。
機能の比較表が以下になります。 *2

f:id:akiyoko:20180616115941p:plain
Features - PyCharmより引用)


この中で私が考える Professional 版のメリットはズバリ、以下の三点です。

  • ファイルの同期とリモートデバッグ(Remote development capabilities)
  • データベースのサポート(Database & SQL support)
  • Django などの各種フレームワークのサポート(Python web frameworks)


まず、「ファイルの同期とリモートデバッグ」は、私が Professonal 版を選んでいる一番大きな理由です。ファイルの同期とはその名の通り、Vagrant や AWS の外部サーバに SFTP 等で自動的にファイルを同期してくれる機能で、実サーバで動作検証する際に非常に便利に使うことができます。リモートデバッグとは、サーバで動作させている Django のプロセスをブレークポイントで止めて IDE 内でステップ実行できる便利機能です。pdbを使ってコンソールでデバッガを使うのと比較して、見慣れた環境でデバッグできるのため効率が劇的に上がります。

二点目の「データベースサポート」は、IDE 内でデータベースのレコードを表形式で表示したり、表のセルを更新することでレコードを直感的に変更できたりと、データベースの操作を IDE 内で統合的に使えるようにしてくれる機能です。
f:id:akiyoko:20180616163255p:plain
SQLite については良さげなクライアントツールがないので個人的にこの機能は重宝していますが、例えば MySQL であれば Sequel Pro、PostgreSQL であれば「PSequel」などのクラアンとツールがあれば特に必要ないとは思います。あと、ER図の作成機能があるので、プロジェクトによってはニーズはあると思います。

akiyoko.hatenablog.jp


最後の「Django などの各種フレームワークのサポート」ですが、例えば Django の場合であれば、テンプレートエンジンに合わせたシンタックスのハイライトや、ファイルに合わせたコード補完をサポートしてくれます。これらの機能はあればもちろん便利なのですが、私の感覚では必要不可欠とまでは言えないように感じています。詳しい情報は「Web Development and Django Support - Features | PyCharm」を参考にしてください。


ちなみに後述する通り、 学生は無料で Professional が使えるので、問答無用で Professional 版を利用すればよいと思います。


ライセンスと料金体系

以降で、Professional 版のライセンスについて説明します。

2017年以降はそれまであった「永久ライセンス」は無くなり、「サブスクリプションライセンス」方式になりました。PyCharm のサブスクリプションは、継続年数によって値段が異なるので少しややこしいです。また、基本は年払いですが、初年度に限り月払い(継続課金)も可能です。 *3

ライセンスは、PC1台ごとではなく、ユーザー1人ごとの料金になっています。ライセンスが1つあれば複数マシンで(別のOSでも可)利用できるのは嬉しい限りです。ただし、同一のユーザーが使うという前提でなければいけません。 *4


次に、コマーシャルライセンスとパーソナルライセンスの違いについて説明します。両者に機能的な差はありません。目的(開発するものが企業の製品・サービスなのか否か)によって、そのライセンスが異なります。パーソナルライセンスは、個人用に使うため(企業ではなく自分のお金で自分のために使う)のものですが、商用サービスの開発にも使えるとのことです。 *5 企業の業務内で利用する場合はコマーシャルライセンスを使いましょう、とのこと。 *6


そして気になる料金体系はこちら。
正確な値段については、公式サイトを適宜ご確認ください。


【パーソナル(個人)ライセンス】 *7

継続年数料金(年額)
1年目89.00 USドル /年
2年目71.00 USドル /年
3年目以降53.00 USドル /年


【コマーシャル(企業)ライセンス】 *8

継続年数料金(年額)
1年目199.00 USドル /年
2年目159.00 USドル /年
3年目以降119.00 USドル /年


また、大学のメールアドレスなど何らかの証明が必要となりますが、学生であれば無料で Professional 版が利用できます(PyCharm だけでなく JetBrains 社の全製品が無料になります)。 *9

私は個人的に有料の Professional版を利用していますが、以降で説明する内容は無料の Community 版でも問題なく動作させることができますのでご安心ください。



Django 開発環境を PyCharm CE で構築するまでの手順

手順の解説

今回の手順について、全体像となぜそのようにするのかを Q&A形式で説明します。

まず、全体像はこちらになります。

f:id:akiyoko:20180617162502p:plain


1.Python 3 をインストール

Q.Python 3 のバージョンは何を選べばよい?
A.3.6 系の最新安定版(執筆時点の最新版は「3.6.5」)を選ぶのがよいです。しかしながら 3.5 系でも Django を使う上では特に問題ないと思います。バージョン 3.6 と 3.5 の違いについては以下を参考にしてください。


(参考)

Q.Python 3 はどうやってインストールすればよい?
A.Python 公式サイトからダウンロードしてインストールするのが一番簡単です。macOS の場合は、Python のバージョンが簡単に切り替えられるように Pyenvというツールを使ってインストールすることをオススメしますが、やや手順が面倒になります。同人誌の付録では Pyenv を使ってインストールする手順についても説明しています。

Q.venv とは?
A.仮想環境作成モジュールです。Python 3.3 以降では「venv」が標準で付属しており、Python 3.5 以降は仮想環境を作成するのに(「virtualenv」や「pyvenv」ではなく)「venv」が推奨されています。 *10

Q.pip とは?
A.Django などの Python パッケージをインストール・アンインストールするためのパッケージ管理ツールです。Python 3.4 以降では「pip」が標準で付属しています。 *11


2.PyCharm をインストール

Q.なぜ PyCharm を使うの?
A.開発しやすいのが一番の理由です。そのほか、「venv」(仮想環境を作成するためのモジュール)や「pip」(パッケージ管理ツール)に詳しくなくても PyCharm の画面をポチポチ操作するだけで仮想環境を作れたり、ライブラリをインストールしたりできるので、初心者にも優しいツールになっています。

Q.初期設定は?
A.PyCharm は「out of the box(箱から取り出してすぐに使える、難しい設定などは一切なしで使える)」というのが大きな魅力のひとつですので、インストール直後の状態でほとんどそのまま使えます。より開発しやすくするための最低限の設定については、拙ブログの過去記事「 PyCharm のオレオレ最強設定 - akiyoko blog」を参考にしてください。


3.PyCharm プロジェクトを作成

Q.PyCharm プロジェクトを作成するときに何を指定すればよい?
A.ワークスペースのディレクトリのパス、仮想環境のディレクトリのパス、Python インタープリタのパスを指定します。ワークスペース以外はプロジェクト作成後でも指定できますが、プロジェクト作成時に済ませておくことをオススメします。

Q.ワークスペースのディレクトリは何を設定すればよい?
A.私はデフォルトのディレクトリを使っています。macOS であれば「~/PycharmProjects/」がデフォルトのワークスペースを配置する場所になります。

Q.仮想環境のディレクトリのパスは何を設定すればよい?
A.デフォルトのまま、プロジェクトが作成されるディレクトリ直下に「venv」という名前のディレクトリを作ればよいでしょう。

Q.Python インタープリタのパスは何を設定すればよい?
A.macOS であれば「which python3」で表示されるパス (*12)、Windows であれば「where python」で表示されるパスを指定します。

Q.Django をローカルPC にインストールするのはなぜ?
A.以下の理由があります。

  • Django に同梱されている django-admin.py(Django 管理コマンドユーティリティ)でプロジェクトのひな形を作るため
  • プロジェクトのひな形作成時に生成される manage.py(プロジェクト管理コマンドユーティリティ)でアプリケーションのひな形を作るため
  • PyCharm 上で Django モジュールへのコードジャンプができるようにするため



以降で、無料版 PyCharm で Django 開発環境を構築するまでの手順を実際に進めていきます。なお、私の環境は macOS 10.13(High Sierra)でそれを前提に進めていきますが、Windows 環境でも問題なく進められると思います。



1.Python 3 をインストール

Python 公式サイトから Python 3 をインストールします。
なお、macOS にはデフォルト状態では Python 2.7 が入っています。Windows 10 の場合は Python はインストールされていないと思います。

https://www.python.org/downloads/から、インストーラをダウンロードします。

f:id:akiyoko:20180617173533p:plain


インストーラをダブルクリックしてインストールします。

f:id:akiyoko:20180617174009p:plain:w400

macOS の場合は自動的に PATH に指定されますが、Windows の場合はインストーラ実行時に「Add Python 3.6 to PATH」をクリックして PATH に追加します。

f:id:akiyoko:20180617174021p:plain:w350


今回の場合では、macOS では「python3」として実行できるようになります(Windows の場合は「python」)。


(macOS 10.13 の場合)

$ python3 --version
Python 3.6.5

$ which python3
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3

(Windows 10 の場合)

> python --version
Python 3.6.5

> where python
C:\Users\akiyoko\AppData\Local\Programs\Python\Python36-32\python.exe

 

2.PyCharm CE をインストール

https://www.jetbrains.com/pycharm/download/から、Community 版である「PyCharm CE」のインストーラをダウンロードします。

f:id:akiyoko:20180617174742p:plain


インストーラをダブルクリックしてインストールを完了させます。



PyCharm CE を起動すると、いくつか初回設定を選択する画面になりますが、こちらは自分のスタイルに合わせて適宜選択します(後で変更し直すこともできます)。

なお、最初に出てくるキーマップ(keymap scheme)は、以前から使っているユーザーであれば「Mac OS X 10.5+ keymap」がよいかと思います。PyCharm 公式ショートカット一覧(Windows版 / Mac版)も非常に役立ちます。

f:id:akiyoko:20180617174858p:plain:w500
f:id:akiyoko:20180617174913p:plain:w500
f:id:akiyoko:20180617174927p:plain:w500
f:id:akiyoko:20180617174940p:plain:w500



3.PyCharm プロジェクトを作成

PyCharm プロジェクトを作成するには、PyCharm 起動後に「Create New Project」をクリックします。

f:id:akiyoko:20180617175016p:plain:w400

次の内容を入力してプロジェクトを新規作成します。
この際、「Virtualenv」を指定することで、プロジェクトごとに仮想環境が作成されます(仮想環境のディレクトリ名は「venv」としています)。 *13

項目設定値
Location:「/Users/akiyoko/PycharmProjects/mysite」
New environment using:「Virtualenv」
Location:「/Users/akiyoko/PycharmProjects/mysite/venv」
Base interpreter:「/Library/Frameworks/Python.framework/Versions/3.6/bin/python3」(「which python3」の実行結果をコピー&ペースト (*14))

f:id:akiyoko:20180617175028p:plain

PyCharm プロジェクトが作成されました。

f:id:akiyoko:20180617175045p:plain


「Preferences」(⌘ + ,)から「Project Interpreter」を開き、下部の「+」ボタンをクリックして、Python パッケージをインストールする画面を開きます。

f:id:akiyoko:20180617175102p:plain

例えば、「Django」を検索して、現時点の 2系の最新版である「2.0.6」をインストールします。

f:id:akiyoko:20180617175118p:plain

依存パッケージを含めてインストールが完了しました。

f:id:akiyoko:20180617175143p:plain

次に、左下のアイコンをマウスオーバーして「Terminal」を選択すると、仮想環境がアクティベートされたターミナルが起動します。

f:id:akiyoko:20180617175200p:plain

アクティベートされない場合は、「Preferences」から[Tool]>[Terminal]>[Activate virtualenv]にチェックが入っているかを確認してみてください。

f:id:akiyoko:20180617175224p:plain

それでもダメな場合は、仕方なく以下のコマンドを実行します。

$ source venv/bin/activate


 
最後に、ターミナル上で次のコマンドを実行して、Django プロジェクトのひな形を作成します。設定ディレクトリ名は拙書に倣って「config」としています。

(venv) $ django-admin.py startproject config .


これで PyCharm で Django を開発する環境が整いました。


最後に

最後に一番大事な話。
4月に「技術書典4」で販売して即完売した「現場で使える 基礎 Django」が、現在増刷して絶賛発売中です!

無償の PyCharm CE を利用すれば、仮想環境を作成するための「venv」やパッケージ管理ツールの「pip」のことがよく分からなくても、Python 開発のためのプロジェクトを簡単に作成することができます。今回紹介した手順に従えば、Django の開発環境もラクラクと構築することができると思います。これで安心して Django の開発に取り組めますよね。あとはこの本を読んで勉強するだけですよね。

booth.pm


この本は B5サイズ・148ページの 本格的な Django 解説書 ですが、Django を仕事の現場で6年ほど使っている私が 「現場でこんな本があったらなぁ」という想いで書いたので、仕事で使っているあなたにぴったりな本に仕上がっているはずです。
そしてこの本は特に、

  • Django の日本語書籍が無くて困っている方
  • Django で一度挫折したことがある方

に絶対オススメの一冊となっています。


過去記事で読みどころの解説や読者の方々の評価を紹介していますので、気になる方はこちらも合わせてご覧ください。

《過去記事》
akiyoko.hatenablog.jp

仮想通貨税金計算サービス「BITCOINTAX」をリリースしました

$
0
0

アカウント登録不要、完全無料で利用できる税金計算サービス「BITCOINTAX」をリリースしました


もっと手軽に仮想通貨取引の税金計算を!
ドラッグ&ドロップだけで使える税金計算サービスが登場


f:id:akiyoko:20180213212659p:plain



【 サービスURL 】
 BITCOINTAX : https://bitcointax.jp/


 

背景

「ビットコイン」「NEM」「仮想通貨」などといったキーワードが連日のようにニュースを賑わせるようになり、ビットコインを始めとする仮想通貨が国内で広く認知されるようになってきました。仮想通貨を売買できる取引所も金融庁に仮想通貨交換業者として登録された業者を中心に競い合うように次々と設立され、スマホで手軽に仮想通貨の取引ができるようになった一方で、仮想通貨取引にかかる税金計算は複雑で、専門知識のない人にとっては非常にストレスフルな作業になってしまいがちです。


昨年12月に国税庁から「仮想通貨に関する所得の計算方法等について」という資料が公表されましたが、特に仮想通貨同士の売買については取引当時の時価を計算する必要があるなど計算は煩雑です。国内の取引所ならまだしも、国外の取引所で売買した場合の日本円での時価は容易には算出できず、国税庁の方針に従って税金計算をするには困難を極めます。


2月16日より平成29年分の所得税等の確定申告受付が開始されるにあたり、これから仮想通貨の税金計算をしようとする人がその煩わしさに途方もない時間を奪われてしまう人が多く出てしてしまうことが懸念されます。最近になって仮想通貨の税金計算サービスがいくつかリリースされ始めてきましたが、いずれのサービスもアカウント登録が必要であったりと手軽に使えるものがありませんでした。


そこで「BITCOINTAX」は、

  • アカウント登録不要
  • 取引所の取引履歴ファイルをドラッグ&ドロップするだけ
  • 無料で全ての機能が利用可能

という特徴を備え、誰でも簡単に使える税金計算サービスとしてリリースいたしました。

なお、現在の対応取引所は、bitFlyer*1)、CoincheckZaif*2)、bitbankBITPointPoloniexBittrexBinanceHitBTCCryptoBridgeの計10種類となっておりますが、要望次第で随時対応を予定しています。


【お知らせ】
  • Bittrex 対応済み(2018年2月15日更新)
  • ご指摘を受けて一部計算の誤りを修正しました。お手数ですが、16日以前に利用された方は再度計算し直してください(2018年2月16日更新)
  • BITPoint 対応済み(2018年2月17日更新)
  • Zaif 対応済み(2018年2月18日更新)
  • Binance 対応済み(2018年2月18日更新)
  • CryptoBridge 対応済み(2018年2月19日更新)
  • HitBTC 対応済み(2018年2月21日更新)
  • bitbank 対応済み(2018年2月23日更新)


なお、他の取引所への対応やバグの修正依頼は、admin@bitcointax.jp 宛にご連絡ください(取引履歴ファイルを添付していただけると助かります)。




日本における仮想通貨のさらなる発展と、仮想通貨に携わる方々のストレスが少しでも解消されることを願っています。




【 サービスURL 】
 BITCOINTAX : https://bitcointax.jp/


 

使い方

BITCOINTAXにアクセスし、各取引所でダウンロードした CSV形式(取引所によっては Excel形式)の取引履歴のファイルをドラッグ&ドロップするだけで利用可能です。


f:id:akiyoko:20180213214829g:plain


アカウント登録などの面倒な作業無しに、すぐに使うことができます。



【 サービスURL 】
 BITCOINTAX : https://bitcointax.jp/


 

その他の特徴

  • 複数ファイルをまとめてドラッグ&ドロップすることも可能です(最大5ファイル・1MBまで)
  • 計算結果が表示された後に、続けて別の取引所のファイルをアップロードできます(計算が全てやり直されます)
  • 計算結果が表示された後に、計算結果を CSV形式でダウンロードできます(ダウンロードした CSVファイルを再びアップロードすることもできます)
  • アップロードされたファイルはサーバで保持していません

 

計算方法

  • 時価計算方法は移動平均法による *3
  • 時価計算には以下のデータを使用
    • bitFlyer の各通貨の時価については、Cryptowatch APIが提供している1〜6時間足データを使用
    • Coincheck の各通貨の時価については、Coincheck が提供している日足データを使用
    • Zaif の各通貨の時価については、Zaif が提供している日足データを使用
    • bitbank のビットコインの時価については、bitbank.cc APIが提供している時間足データを使用
    • Binance の各通貨の時価については、Binance API が提供している日足データを使用
    • CryptoBridge の各通貨の時価については、CoinMarketCap が提供している日足データを使用(ただし、120通貨中 63通貨のみ。2018年2月19日現在)
    • 上記以外の海外取引所の各通貨の時価については、Kraken(BTC/USD)Poloniex APIが提供している時間足データを使用(2018年2月20日更新)
    • 海外取引所の場合の USD/JPY については、ドル円為替の日足データを使用
    • 2016年1月以降のデータを使用しているため、2015年12月以前の取引がある場合には対応できない場合があります

 

免責

  • 本サービスは予告なく停止、終了、仕様が変更されることがあります
  • 本サービスの利用によって生じたいかなる損失または損害については一切の責任を負いません

 


【 サービスURL 】
 BITCOINTAX : https://bitcointax.jp/


 

問い合わせ先

パブリックな問い合わせは GitHub Issue、プライベートな問い合わせは admin@bitcointax.jp または Twitterにお願いします

*1:現物取引のみ。bitFlyer Lightning(ビットコイン現物・FX・先物取引、イーサリアム現物の取引)には未対応です。

*2:現物取引のみ。信用取引・AirFX取引・先物取引には未対応です。

*3:参考:「移動平均法(棚卸資産の評価方法)の仕訳・会計処理 | 仕訳NET

これぞベスト・オブ・Django 本!『現場で使える Django の教科書《基礎編》』が Kindle で販売中

$
0
0

akiyoko です。

8月に Kindle 版『現場で使える Django の教科書《基礎編》』を販売しました。技術書典4 で頒布した『現場で使える 基礎 Django』の改訂本です(書籍名も変更しました)。

全面的な修正と36ページ(本文144→180ページ)の加筆をおこない、まさに「Django を現場で使うための基礎知識」として十分な内容になっているものと自負しています。


◆ Kindle(電子版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

◆ Kindle(ペーパーバック版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》



改訂内容

技術書典4 版より、以下の加筆をおこなっています。

  • Django 2.1 対応(第4章など)
  • 設定ファイルについて大幅加筆(第10章)
  • マイグレーションについて加筆(第11章)
  • Docker の活用について加筆・修正(第15章・付録D)
  • Python 3、PyCharm のインストールなど初心者向けの付録を追加(付録AをA・B・Cに拡充)
  • 表紙(デザイン by 橋本 OSO 鉄也さん)

なお、技術書典4 版の読みどころについては過去記事にガッチリ書かせていただきましたので、興味ある方はぜひご参照ください。

《過去記事》
akiyoko.hatenablog.jp


対象読者

本書の対象読者としては、

  • Python の文法はある程度分かるけど Django は初めてという初心者の方
  • Django を始めてみたけど今いちコツが掴めないという初級者の方
  • Django のベストプラクティスを学びたいと考えている中級者の方

を想定しています。特に、

  • Django の日本語書籍が無くて困っている方
  • Django で一度挫折したことがある方

にピッタリな再入門書にもなっていると思います。
しかしながら、Webアプリケーション開発の経験がまるっきり無いという方には多少難しい内容になっているかもしれません。

目次

目次は次の通りです。
本文は全部で180ページです(目次およびあとがきを含む)。


第1章:はじめに
第2章:アーキテクチャ
第3章:プロジェクト構成
第4章:URLディスパッチャと URLconf
第5章:ビュー(View)
第6章:モデル(Model)
第7章:テンプレート(Template)
第8章:フォーム(Form)
第9章:ミドルウェア(Middleware)
第10章:設定オブジェクトと設定ファイル(settings.py)
第11章:データベースのマイグレーション
第12章:開発用 Web サーバ(runserver)を起動する
第13章:管理サイト(Django Admin)
第14章:便利な Django パッケージを使おう
第15章:サンプルコード
付録A:Python3 のインストール手順
付録B:PyCharm のインストールと初期設定
付録C:PyCharm による Django 開発環境の構築手順
付録D:Docker でラクラク開発
付録E:覚えておきたい Django 管理コマンド10選



f:id:akiyoko:20180930125128p:plain:w190

f:id:akiyoko:20180930125146p:plain:w190

f:id:akiyoko:20180930125206p:plain:w190



Amazon レビューより

ありがたいことに、Amazon レビューで非常に良い評価をいただいています。
いくつか紹介させていただきます。

日本語情報の少ない、待望のDjango書籍です。Django2にも対応しています。
膨大な機能のあるDjangoフレームワークの、主要な機能をわかりやすく解説しています。
図や表もよく出てきて良い感じです。
その機能がどう動いているか、どういう流れなのかといった解説もあり、フレームワーク自体への理解も助けてくれるでしょう。


個人的には、何らかのチュートリアルが終わった人、一度挫折した人、新しいDjangoを知らない人に特にオススメです。
よくまとまっていますし、いくつかのベストプラクティクスと一緒に学ぶことができます。

Djangoの最新版に対応した日本語の書籍ということで貴重な書籍だと思います。
内容も実際に業務を行う上でのポイントもかかれており、実際にDjangoで何かWebサービスを作成するうえで役に立つ本だと思いました。
公式のチュートリアルを行ってから読むとDjangoの理解が進むと思います。

プログラマーの為の実践向け書籍。
django を勉強したけど、よく理解できなかった人向け。
django 公式ドキュメントで疑問に思った多くの事を補完できた。


まとめ

これぞ「ベスト・オブ・Django 本」と言えるような本ができました。
私自身仕事で Django を使っていて「Django の基礎知識がちゃんと書いてある本がほしいなぁ」という想いで書いた本なので、特に、仕事の現場で Django を使っている人に読んでいただきたいと思っています。

ということで現在、Kindle にて『現場で使える Django の教科書《基礎編》』が絶賛販売中です! 現場に一冊、ぜひともよろしくお願いします。


◆ Kindle(電子版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

◆ Kindle(ペーパーバック版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》


【追記】
10/8(祝・月)の 技術書典5で、続編の『現場で使える Django の教科書《実践編》』を頒布予定です。ぜひ遊びにきてください!!

techbookfest.org

speakerdeck.com

薄いのに?薄くない! 技術書典5 で Django の薄い本の第二弾『現場で使える Django の教科書《実践編》』を頒布します

$
0
0

akiyoko です。

10/8 の「技術書典5」で、二作目の技術同人誌 『現場で使える Django の教科書《実践編》』を頒布します。先週末にすでに入稿完了したので、あとは当日を待つのみです。




《実践編》はどんな内容?

全176ページまるまる Django 本です。
Python についての解説は一切ありません。

前回の技術書典4で出した『現場で使える基礎 Django』(*1)の続編にあたりますが、続編といっても Django の基本的な知識を有する方であれば理解できる内容の本になっていますのでご安心を。

前作同様、現場で使える知識を中心に、さらに実践的な内容に踏み込んでいます。
たとえば、

  • 認証まわりの機能についての総まとめ+ソーシャル連携認証の仕組みから導入まで
  • ファイルアップロードについての完全解説
  • ユニットテストの仕組みから効率良く書く方法まで
  • クラウド環境に Django サイトをデプロイする手順をイチから分かりやすく
  • 本番公開時のセキュリティについて(チェックシート付き)
  • Django サイトの高速化についての TIPS

などを盛り込んでいます。
詳しくは後述の目次をご参照ください。

いわば全編がベストプラクティスで、現場のノウハウをこれでもかと詰め込んでいます。前作にも勝るとも劣らない、著者渾身の一作です。


なお、本書の読者としては、

  • Django をもっと知りたい方
  • 仕事の現場で本格的に Django を使いたい方
  • 前作《基礎編》を読み終えた方

を想定しています。
特に、前作《基礎編》を読み終えた方には絶対オススメです。なぜなら「基礎のちょっと先」に手を出そうと考えている人向けの本になっているからです。詳しくは後で説明します。


表紙

表紙はちょっと大人っぽいシックなカラーに仕上がっています。今回は 橋本 OSO 鉄也さんというプロの方にデザインしていただきました。前回の緑の表紙は私がお絵描きしたものだったので、ガラッと様変わりしていてパット見、同じ著者のものとは気付かない方もいるんじゃないかなと思います。

Django の語源にもなっている ジャンゴ・ラインハルトセルマーギターや「現場」のコンクリート感など、コダワリ満載です。すごくお気に入りです。



f:id:akiyoko:20180930140739p:plain:w250

f:id:akiyoko:20181002010006p:plain:w250


技術書典の帰り、あるいは通勤通学の電車・バスの中で広げてもまわりがザワザワしない表紙になっています。


目次

気になる目次は、



f:id:akiyoko:20180930140511p:plain:w250

f:id:akiyoko:20180930140547p:plain:w250




第1章: はじめに
第2章: 開発のヒント(認証まわりをサクッと実装)
第3章: 開発のヒント(Bootstrap 4 対応)
第4章: 開発のヒント(Ajax 対応と JSON レスポンス)
第5章: 開発のヒント(ファイルアップロード)
第6章: ユニットテスト
第7章: デプロイ
第8章: セキュリティの TIPS
第9章: 高速化のための TIPS
付録A:メール送信の設定
付録B:Let’s Encrypt で SSL/TLS 証明書発⾏

となっています。

表紙を除いた 本文は全 176 ページ(目次・あとがき含む)です。
文字数は16万字ほどあります(400字詰め原稿用紙 400枚!)。


f:id:akiyoko:20181003024813p:plain:w400

本の厚さは(1円玉より大きい)11 mm 超もあります。全然薄くありません。そしてただ厚いだけでなく、内容も非常に濃いです。執筆は想像を絶するほど大変でした。9月はマジ死にました。。



読みどころ

もちろん全編が読みどころなのですが、中でも特に一番の読みどころは「第7章: デプロイ」で、44ページというちょっとした同人誌一冊分の紙面を使って、クラウド環境への Django プロジェクトのデプロイ手順を一から完全解説しています。そろそろ Heroku を卒業して、自由度の高いサーバに Django をデプロイしてみたいという人には打ってつけの内容になっているでしょう。
OS は Ubuntu 18.04、ソフトウェアは現状の最新のもの(systemd+Nginx+Gunicorn+MySQL 8.0 or PostgreSQL 10.5)を使用。公開鍵を作るという最初の一歩から(*2)最後は Let's Encrypt で常時SSL 化するところまで、一気通貫で説明しています。世の中で一番詳しい Django のデプロイ解説書にもなっているはずです。


「第2章: 開発のヒント(認証まわりをサクッと実装)」も、Django アプリの第一歩として非常に良いリファレンス(参考資料)になると思います。ちょっとした応用編として、ソーシャル連携認証を簡単に実装する方法について、「OAuth って何?」というレベルの方にも分かりやすいようその仕組みから解説しています。


「第8章: セキュリティの TIPS」や「第9章: 高速化のための TIPS」もぜひ読んでいただきたい章です。いざ本番リリースするという段になって、「このまま公開してセキュリティ的に大丈夫なんだろうか?」「何だか遅いように感じるけど何でだろう?」と途方に暮れたことはありませんか? そんな現場のお悩みを解消するヒントをここに書きました。


そのほか読みどころはいろいろあるのですが、もう全部読んでくださいとしか言えません。もし目次の内容で気になるものがあれば、ぜひ買って読んでみてください。中身については絶対の自信があります。知りたかったことが見つかったり、新しい発見があったりするはずです。


《実践編》を書いた理由は?

前作《基礎編》を書いた理由は Django 開発の現場で「Django の日本語の書籍が少ない」とずっと感じていたからでした。そして技術書典4で同人誌を出し、予想をはるかに超える反響をいただきました。想像以上に現場で Django が使われているという実感を持った一方で、「それだったらもっと実践的な内容の本も必要じゃないのか?」と感じたのが今回の本を書いたきっかけです。

当初は《実践編》ではなく《応用編》としてもう少し難しい内容の本を書こうと考えていました。しかしそんなとき、匿名の方からいただいた「《基礎編》やチュートリアルの次は具体的に何をすればいいの?」という質問が目に留まりました。そういった 初級者から一歩踏み出すための教材がまだ全然ないという現状にハッと気付き、だったら「基礎のちょっと先」の本を書いてそれに応えようと考えたのでした。

「次の本」の構想はあったものの、今回の《実践編》を実際に書き始めたのは 8月に入ってからです。そして 8月の半ば頃まではほとんど 《基礎編》の Kindle版を出すための作業をしていたので、執筆期間は実質1ヶ月半くらいでしょうか。書き始めた頃はまさかこんなページ数になろうとは考えもしませんでした。9月は特に酷くて、毎日のように朝までボロボロになるまで書き続けていました(昼間は Django じゃない仕事があって何もできないので・・)。


頒布本情報

当日のお品書きを作りました。
お釣りがなるべく出ないように考慮した「会場特別価格」です。

f:id:akiyoko:20181002011116p:plain:w400

《実践編》は B5サイズ、176ページ。
技術書典5での会場特別価格 1,500円です。

前回の技術書典では新作が3時間で完売したので、今回はドンと倍プッシュしてみました(部数はヒミツ)。当日、来場者の行列を見て「これは買えないな」と思った方でも、もしかしたら買えるかもしれませんよ。


あと、既刊の《基礎編》も多少持っていきます。

f:id:akiyoko:20181003023739p:plain:w400

こちらは先に少し言及したように、Kindle で電子版とペーパーバック(紙)版が絶賛販売中です。ありがたいことに好評をいただいているようです。

◆ Kindle(電子版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

◆ Kindle(ペーパーバック版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》



頒布場所は「か06」の「あきよこブログ」です。
見本誌を置いてますので、立ち読みだけでもお気軽にどうぞ。

techbookfest.org

f:id:akiyoko:20180930143251p:plain


池袋サンシャインシティ2F、10/8(祝・月) 11時オープンです。
午前中は混雑すると思いますのでご注意を。



「Django 島」について

そして、全国の Django 好きの方に朗報!!
何と今回の技術書典5では、Django の新刊が4冊以上は確定。もしかすると、それ以上出る可能性があります。Django 好きのみんな、10/8(祝・月)は池袋に集合やで~!!


*1:8月より、その改訂版の『現場で使える Django の教科書《基礎編》』を Kindle で販売中です。

*2:もっと言うとその前のデプロイ先の選定や Webサーバとアプリケーションサーバの違いの説明から

技術書典5 で頒布される Django / Python の薄い本の情報を集めてみた

$
0
0

akiyoko です。

10/8(祝)の「技術書典5」で薄い本を出します。ブースは「か06:あきよこブログ」です。


今回の技術書典5では、(私のを含めて)何と Django の薄い本が合計7冊(新刊5冊・既刊2冊)も出そうな感じです。Django 好きにはたまらないですよね!



技術書典はドンキ的なごった煮感が好きなのですが、いかんせん技術書典公式の サークルリストには「サークルカット」と呼ばれる一枚絵とサークル名、ざっくりとしたカテゴリが載っているのみで、結局ひとつひとつ目でチェックしていくしかありません。しかも今回は、サークル数が前回のほぼ倍(500サークル弱)に増えたのでそのチェック作業も重労働です。そこで、「私が注目している」という理由から、技術書典5 で頒布される「Django / Python」系の薄い本の情報を集めてみました。そっち系に興味がある方のみどうぞ。


青枠で囲んだ本は「新刊」、グレーの枠は「既刊」であることを示しています。出版社ブースについては本の数が多いので一律、本のタイトルは非掲載としました。なお、10/5 深夜時点の掲載情報を元にしています。販売価格やページ数は今後サークル主によって変更になる可能性があるので(書かなきゃよかった・・)、実際に購入する際は各自でチェックをお願いします。


情報の取得に際しては、Pythonista らしく、Scrapyでスクレイピング・・ではなく、手でひとつひとつ集めました。画像は PyOCR・・ではなく目でチェックしました。抜け漏れはいくつもあるかと思いますがご容赦ください(もし間違えてたら連絡くだされば即対応します)。


そもそも「技術書典」って何?

技術書典」は、春と秋の年二回ずつ開催される、技術者による技術者のための技術系同人誌の販売イベントです。今回が5回目の開催になりますが、回を重ねるごとに認知度や参加者の数、サークルの熱量がどんどん増えていて、公式によると今回は一万人ほどの来場者を見込んでいるとのことです。

techbookfest.org



それでは、手動スクレイピングの成果をお見せします。
順番はサークルの並び順(あいうえお順・ただしスポンサーが先)です。



Python 関連

ス01:株式会社 インプレス(カブシキガイシャインプレス)

techbookfest.org

あ05:データリファインメント(データリファインメント)


Kaggleのチュートリアル第2版(108ページ / ¥1,000)

techbookfest.org

あ10:Secure旅団


俺らの愛したセキュリティ(¥1,000)

techbookfest.org

い07:マークアップ言語愛好会


マスタリング docutils(32ページ)

techbookfest.org

う04:改善屋tech

techbookfest.org

え12:PEAKS


ゼロから創る暗号通貨(304ページ / ¥3,600)

techbookfest.org

え39:つばめさんチーム


趣味のPython(80ページ / ¥500)

techbookfest.org

お21:日経BP出版局

techbookfest.org

か04:仮面の人

techbookfest.org

か09:Thunder Claw


ほぼPythonだけでサーバーレスアプリをつくろう(144ページ / ¥1,000)

techbookfest.org

か19:なにココ


PyCharmのすすめ ~デプロイとデバッグ編~(¥500)

techbookfest.org

か35:株式会社マイナビ出版

techbookfest.org

か49:KLab 株式会社


KLab Tech Book Vol. 2(76ページ / ¥500)

techbookfest.org

き07:eMbLog


PythonでGUIをつくろう〜はじめてのQt for Python〜(120ページ / ¥1,000)
PythonでGUIをつくろう〜はじめてのQt for Python〜(カラー電子書籍版)(120ページ / ¥800)

techbookfest.org

き21:74th


Fabric & Invoke Quick Guide(8ページ / 無料)


PythonタスクランナーFabric & Invokeを活用する技術(本+PDF / 80ページ / ¥1,000)
PythonタスクランナーFabric & Invokeを活用する技術(PDF / 79ページ / ¥800)

techbookfest.org

く05:craft by SKDN


【委託】Hello worldカルタ(¥1,900)

techbookfest.org

く11:暗黙の型宣言


「改訂版」流体計算で覚えるPython3(第2版)(188ページ / ¥500)

techbookfest.org

け02:電脳律速


株とPytnonでお金儲けを目指す本2(42ページ / ¥500)


株とPytnonでお金儲けを目指す本(84ページ / ¥1,000)

techbookfest.org



Django 関連

f:id:akiyoko:20181006210430p:plain

う08:黒塗りのビール


黒ビール好きの【IonicとDjangoの本】(100ページ / ¥1,000)

techbookfest.org

か05:jbking


どじゃんご本#1(72ページ / ¥1,000)

techbookfest.org

か06:あきよこブログ


現場で使える Django の教科書《実践編》(176ページ / ¥1,500)


現場で使える Django の教科書《基礎編》(180ページ / ¥1,500)

techbookfest.org

か07:みる会


Visual Studioで お気楽Web開発 Python + Django(48ページ / ¥300)

techbookfest.org

か08:Route 312


実践レシピ おいしく使うDjango(56ページ / ¥500)

techbookfest.org

け42:しょうゆのさーくる


nuxtとvuesaxとDjangoで作るモダンなサービスの作り方。tipsもあるよ!(28ページ / ¥500)

techbookfest.org


まとめ

Python 盛り上がれ。Django もっともっと盛り上がれ~!

最後に、私のサークルの頒布物まとめ記事もどうぞ。

akiyoko.hatenablog.jp

初学者・初級者向け Django の学習ロードマップ

$
0
0

この投稿は 「Django Advent Calendar 2018 - Qiita」 の1日目の記事です。

akiyoko です。
2018年はまぎれもなく「Django の一年」でした(少なくとも個人的には)。

振り返れば、4月と10月に 技術書典で Django の技術同人誌を出したり、Django Girls Tokyoという女性エンジニア向けイベントのコーチをしたり、モグモグ Djangoのスタッフをしたりと、Django を始めたばかりの方と向き合う機会が特に多かったです。

そんな中、
「Django って難しいよね」
「やってみたけどよく分からなかったので諦めた」
という声を聞くことが何度かありました。

最初は「フルスタックゆえに学習コストが高い」というのが原因なのかなとぼんやり思っていたのですが、最近はそうではなく、Webアプリケーション開発の前に知らないといけない知識やスキルが多すぎる、つまり、Django に至るまでの道のりが長すぎるというのが大きな原因になっているのではないかと考えるようになってきました。


そこで本記事では、「ビフォー Django」(Django に至るまで)と「アフター Django」(Django を学びはじめた後)に分けてそれぞれ必要となる知識やスキルを整理し、それを踏まえて特に初学者・初級者に向けた「Django の学習ロードマップ」を示してみようと考えています。私があれこれ妄想しただけのものなのでもちろん異論反論あるかと思いますが、ジャストアイデアとして温かくご査収いただければ幸いです。


本記事を書くにあたって、Djangoのハマりどころや難しいと感じている点について、Django 経験者に匿名のオンラインアンケートをおこないました。その結果、予想を大きく上回る92名(!)の方から回答をいただくことができました(アンケート期間は11月13日〜28日)。アンケートにご協力いただいた方々にこの場を借りて感謝申し上げます。

docs.google.com


 

ビフォー Django(Django に至るまで)

Webアプリケーションを初めて学ぶという場合は、Django をはじめとした Webアプリケーションフレームワークを学習する前にいわゆる「予備知識」あるいは「前提知識」を身につける必要があります。また、Python 未経験の方であれば、Django 学習のスタート地点に立つために Python の読み書きがひと通りできるレベルのスキルが必要になります。

学習ロードマップ

Webアプリケーションフレームワーク、および Python の基礎を習得するために必要と思われる「Web技術」「データベース」「インフラ」「Python」の知識やスキルの洗い出しをしてみました。レベルについては「ITスキル標準とは?:IPA 独立行政法人 情報処理推進機構」を参考にしてみました(が、雰囲気程度です)。


f:id:akiyoko:20181201110838p:plain
(図1.Django 以前に必要な知識・スキル)


これらを最低限レベル2まで習得した上で、ようやく次のステップである Django という土壌に立てるわけです。そりゃあしんどいですよねぇ。

なお、レベル3 のスキルについては案件に応じて獲得する必要がありますが、すべての場合において必須というわけではありません。

学習方針(案)

新しい言語やプロダクトの学習をする場合の学習法は世の中にたくさんありますが、

  • 書籍を読む(技術同人誌や電子版を含む)
  • オンラインチュートリアルを読む(非公式のものも含む)
  • ブログ記事を読む *1
  • プログラミングしながら学べる学習サービスで学ぶ *2
  • 動画学習サービスで学ぶ *3
  • 勉強会に参加する *4

くらいに分類できるかと思います。それぞれの学習法にはメリット・デメリットがあります。たとえば、次のような感じです。

f:id:akiyoko:20181201114854p:plain:w550


当たり前ですが、自分のレベルや好き嫌いに合った学習法をオススメします。

また今回のアンケート結果から、

  • 若い人ほど、ブログで学習する(相関係数 r=0.19)
  • 若い人ほど、プログラミング学習サービスで学習する(r=0.21)

という分析結果が得られました。経験がある人は二次情報を見ない(一次情報をあたる)という傾向を表しているのでしょうか。効率から言えば一次情報にあたる方がよいのでしょうが、経験が浅い人からすると最初は何が分からないかも分からない状態なので、「〇〇とは」系の簡単なブログ記事で全体像や雰囲気をざっくり掴むところから入るのがよいでしょう。


本記事の最後に、私がオススメする教材リンクを掲載しました。初学者向け(★)、初級者向け(★★)、脱初級者〜中級者向け(★★★)に分けて紹介していますので、ご自身のレベルに合わせて参考にしてください。



アフター Django(Django を学びはじめた後)

ようやく Django を学習しはじめたところで、ここでフルスタック由来の「学習コスト高い問題」という壁が立ちはだかります。

まずは、アンケート結果から見ていきます。

難易度

「Djangoは難しいと感じますか?」という問いに、4人に1人の方(全体の25%)が「Django は難しい」と回答しました。「簡単」と答えた方は10人に1人(9.8%)しかいませんでした。


f:id:akiyoko:20181201085304p:plain:w450
Q4.「Djangoは難しいと感じますか?」

Q3.「Django の経験はどのくらいですか?」の結果によると回答者の多く(63%)が「Django 経験が1年未満」だったことから、単に「難しい」の割合が「簡単」の割合よりも多いというだけで「Django =難しい」とは言い切れません。次に示すのは、Django の経験年数ごとに難易度の度数を集計した度数分布表です。パッと見て、経験1年未満で「難しい」と答える割合が多かった(「1年未満」の36.2%が「難しい」と回答)ことが分かります。「Django 経験年数」(階級値を使用)と「難しいと回答した割合」の相関を調べると、やはり 経験が浅い人ほど「難しい」と感じる傾向が大きいことが分かりました(弱い相関 r=0.24)。


f:id:akiyoko:20181129012004p:plain:w550
表.Django 経験年数ごとの難易度の度数分布表


ハマりどころ

「Djangoでハマったところ、あるいは難しいと思うところはどこですか?」という問いに対する回答結果(選択方式・複数回答可)を得票順に並べ替えたのが、次のグラフです。

f:id:akiyoko:20181130235710p:plain
Q5.「Djangoでハマったところ、あるいは難しいと思うところはどこですか?」


「全体像を理解するのが難しい」と回答した方が最も多かったです。そしてまた、初学者や初級者が多いと思われる「経験1年未満」のグループで「全体像」と答えた割合が特に多かったことも分かりました(次に示す Django 経験年数ごとの度数分布表を参照)。初学者や初級者は最初のイメージを掴むところでつまづいてしまう、というのがあるのでしょう。

f:id:akiyoko:20181130235624p:plain
表.Django 経験年数ごとのハマりどころの度数分布表

ハマりポイントの第2位は「デプロイ」でした。こちらも「1年未満」のグループで「デプロイ」を挙げる方が多かったようですが、これについては、初学者が手始めに利用することの多い Django Girls チュートリアルの後半に突如として出てくる Heroku へのデプロイでつまづいてトラウマになった人が多かったのでは?というのが個人的な見解です。最近リニューアルした 新バージョンの Django Girls チュートリアルのデプロイでは PythonAnywhereというよりシンプルな環境を使うように改良されているので、つまづくことはだいぶ少なくなっていると思います *5。一度諦めていた方もぜひ再チャレンジを。

ハマりどころとしては以下、「ビュー」「ユニットテスト」「静的ファイル」と続いています。ビューやユニットテストについては、Django が用意してくれているクラスを継承して簡単に書ける反面、何をオーバーライドして使えばよいのかがブラックボックスになっていて分かりづらいという点がハマりどころになっているのではないかと想像します。このあたりは現時点ではまとまったよい情報がほとんどなく、「ソースコードを読めば分かる」的な側面もあります。


そのほか、上の度数分布表を見ると経験が「1~3年」のグループでは「フォーム」「静的ファイル」「ユニットテスト」が多くなっていて本格的に使い始めている感じがするなど Django の経験年数によってハマりどころが変化しているところや、セットで利用されることが多いからでしょうか、フォームとテンプレートのハマり度に相関があった(相関 r=0.56)のは、非常に興味深かったです。

学習ロードマップ

以上のアンケートと私の経験を踏まえて、Django についてはこのような学習ロードマップを提案してみたいと思います。


f:id:akiyoko:20181201102426p:plain
(図2.Django 以降で必要な知識・スキル)


学習方針(案)

真っ先に全体像を把握するところから始めます。フルスタックである Django がカバーしている範囲を見極めることや、機能単位で分離している構成要素(コンポーネント)同士のつながりを把握することが重要であると考えるからです。


全体像を把握した後は、簡単な Django プロジェクトのサンプルを作成して動かすのがよいでしょう。 Django にはプロジェクトのひな型を作るためのコマンド(startproject)や簡易的な Webサーバを実行するコマンド(runserver)があらかじめ用意されているため、導入部分をチュートリアル形式で学ぶというスタイルとの相性がよいです。

そして「Django はチュートリアルで十分」という意見も多く出るくらい、Django は非常にチュートリアルが充実しています。*6有名どころでいえば、

などが挙げられるでしょうか。

その中でも「Django 公式チュートリアル」から入る初学者の方が多いと思いますが、少し注意が必要です。というのも、公式チュートリアルには図が一切なく、全体像が把握しづらいです。あと、大事なところをしれっとすっ飛ばしたり、リンクで逃げて説明していなかったりと少し不親切なところも散見されます。したがって、初学者・初級者向けには少し分かりづらいかもしれないと感じています。あと、「ビフォー Django」の内容については触れられていません。

ちなみに Django 公式チュートリアルは完全に日本語翻訳がされていますが、リンクをたどった先がほとんど英語のままになっていることも多いです(ドキュメント全体の3〜4割しか翻訳できておらず *7、特に詳細レベルの内容については翻訳されていないものが多い)。英語が苦手なエンジニアはそこで腰が引けてしまうかもしれません。


「ビフォー Django」をきちんと学習してこなかった方には「Django Girls チュートリアル」をオススメします。インターネットの仕組みやコマンドラインの使い方から、HTML や CSS などの基礎的な話についてもカバーしてくれています。ただし先に述べた通り、途中に出てくるデプロイやそれに付随する Git の習得については非エンジニアの方にはレベルが高すぎるため、とりあえずはすっ飛ばしてもよいでしょう。


次のレベルとなるプロレベルの基礎知識としては、各コンポーネントの詳細な使い方や書き方、Django で特に充実しているユーザーまわりの機能について把握しておく必要があるでしょう。本格的に仕事で使う場合には、ユニットテストの書き方についても理解しておく必要があります。「Django パッケージ」は開発効率を格段に向上させるので、積極的に導入したいところです。また、個人的にハマりポイントが多いと感じている「静的ファイル・メディアファイル」についても必要になるケースが多いため、正しい知識をインプットしておきましょう。


このように Django についても、全体から詳細へ、というパターンで学習することをオススメします。この記事の最後に私がオススメする教材リンクを掲載しました。初学者向け(★)、初級者向け(★★)、脱初級者〜中級者向け(★★★)に分けて紹介していますので、ご自身のレベルに合わせて参考にしてください。


オススメ教材リンク(ビフォー Django)

私の観測範囲がビフォー Django について疎いため、網羅的にカバーしきれていません。あとで追加するかもです。

初学者向け(★)

《 Web技術 》

超絶初心者のためのサーバとクライアントの話(ブログ)
qiita.com


『イラスト図解式 この一冊で全部わかるWeb技術の基本』(書籍)

買って読みましたが、図+簡潔な説明で書かれていて非常に分かりやすかったです。


HTML & CSS | Progate [プロゲート](学習サービス)
prog-8.com


JavaScript | Progate [プロゲート](学習サービス)
prog-8.com


《 データベース 》

SQL | Progate [プロゲート](学習サービス)
prog-8.com


《 インフラ 》

Command Line | Progate [プロゲート](学習サービス)
prog-8.com


《 Python 》

Python のバージョンは、よほどの事情がない限り「Python 3」を勉強しましょう。文字コードの扱いが大変すぎますし、何より、Django の新バージョン 2.0 以降では Python 2 はサポート外になっていますので。


Python | Progate [プロゲート](学習サービス)
prog-8.com


『スラスラ読める Pythonふりがなプログラミング』(書籍)

小学生でも読めてしまう、画期的な Python 参考書です。


『Python3 入門ノート』(書籍)

入門者にもやさしく、最後に少し機械学習の導入部分まで学べる一石二鳥の本。


『Pythonチュートリアル 第3版』(書籍)

Pythonの作者 Guido van Rossum が書いた本の翻訳書です。私も持っている Python の資格試験「Python 3 エンジニア認定基礎試験」の教材にもなっていますので、この本をマスターすれば Python の資格もバッチリです。


初級者向け(★★)

《 Python 》

Django に限っていえば、基本文法と仮想環境の使い方、Python パッケージの活用だけで十分です。Django の前提知識としては、そのあたりを押さえておけばよいでしょう。


『Pythonエンジニア ファーストブック』(書籍)

ついでに Django 基礎知識も学べる一石二鳥の本。まるまる一冊 Django ではないですが一章分(70ページ)割いています。


脱初級者〜中級者向け(★★★)

《 インフラ 》

『体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践』(書籍)

「徳丸本」と呼ばれているほど有名なセキュリティ対策本の第2版。


オススメ教材リンク(アフター Django)

初学者向け(★)

《 全体像 》

全体像をつかむための一枚絵などの情報は意外と少なかったです。


Djangoフレームワークの紹介(その他)

Django 界隈で有名な tokibito さんのスライドです。


Rails以外全くわからないマンがDjangoに触れてみて驚いたRailsとの違い - Qiita(ブログ)

Rails から来た人が最初に読むと全体像がつかめて分かりやすいです。

qiita.com


《 チュートリアル 》

プロジェクトの作成からはじまり、runserver で管理画面を確認して、簡単な機能を実装するところまでをひと通りおさえるというチュートリアルがよくあるパターンです。Django ではチュートリアル系の情報が大変充実しています。


Django Girls チュートリアル(チュートリアル)

大人気のチュートリアルです。非エンジニアなどの超初心者ならこちらをオススメします。インターネットの仕組みやコマンドラインの使い方から HTML や CSS など、初歩の初歩からステップ・バイ・ステップで解説してくれています。

古いバージョンのものは Heroku にデプロイするようになっていて結構ハマる人がいましたが、リニューアルされたものは PythonAnywhere にデプロイする形に書き直されていて、ハマることは少なくなっているはずです。

なお「Girls」と付いていますが、女性じゃなくてもウェルカムだそうです。もともとは世界的な女性向けイベントのために作られたサイトを各国語で翻訳したものです。

はじめに · Django Girls Tutorial


公式チュートリアル(チュートリアル)

初学者にはちょっと難しいところもあるかもしれませんが、安心と信頼の公式チュートリアルです。

はじめての Django アプリ作成、その 1 | Django documentation | Django


Python Django入門 (1)(ブログ)

ブログ系で Django のチュートリアルを勉強するなら、これがよいでしょう。

qiita.com


Django入門編1: Djangoの基本を理解しよう | プログラミング学習サービス【paizaラーニング】(動画学習サービス)

11月29日に「Django」の講座が追加されました。早速やってみましたが、初心者にもやさしい系でした。「エル、エス、エンター!」

paiza.jp


『プログラミング初心者でも安心、Python/Django入門講座』(動画学習サービス)

Udemy の Django 講座をいくつか受講しましたが、その中で圧倒的に良かったのがこの narito さんの『プログラミング初心者でも安心、Python/Django入門講座』です。Udemy は頻繁にセールをやっているので、それを狙って気になった講座をまとめて買うのもよいでしょう。

プログラミング初心者でも安心、Python/Django入門講座 | Udemy


DjangoBrothers チュートリアル(チュートリアル)

比較的新しいチュートリアルで、しっかり Django 2系です。解説も丁寧でやさしいです。

www.djangobrothers.com


Python Django 超入門(書籍)

そもそも Django の書籍は少ないので貴重です。超初心者向けならこの本です。ちなみに電子版はありません。


『Django for Beginners: Learn web development with Django 2.0』(書籍)

英語に問題がないなら、Django 本の選択肢は広がります。こちらは実用系チュートリアルの本でレビューの評価も非常に高いです。私も読みましたが、英語も比較的容易なものでした。Vincent さんの記事はネットでたまにヒットしますが、非常に信頼がもてる記事を書いています。


Django チュートリアル| MDN(チュートリアル)

まだ鋭意翻訳中ですが、初心者向けのページからテスト、デプロイ、セキュリティまで、非常に守備範囲の広いチュートリアルになっています。今後に期待。

developer.mozilla.org


初級者向け(★★)

『現場で使える Django の教科書《基礎編》』(書籍)

私の技術同人誌です。現場レベルの Django の知識を扱った日本語書籍はまだまだ少ないので貴重です。チュートリアル形式ではありませんが、コンポーネントごとの仕組みや書き方、ベストプラクティスまでを解説しています。

読みどころについては、ブログの過去記事で解説していますので、興味ある方はぜひ。

akiyoko.hatenablog.jp



脱初級者〜中級者向け(★★★)

『現場で使える Django の教科書《実践編》』(書籍)

10月の技術書典で新刊として出した私の Django の薄い本の第二弾で、開発の現場で必要になる知識やよくある問題へのヒント・解決策を中心に、デプロイやセキュリティ、高速化などさらに実践的な内容に踏み込んでいます。ユニットテストについて解説した章もあります。

今時点では BOOTHという(技術同人誌を含めた)同人誌を多く扱ったオンラインショップでの販売のみになっていますが、現在鋭意、Amazon で電子版を販売する準備を進めています(今月上旬販売予定)。

booth.pm



『Two Scoops of Django』(書籍)

世界的に有名な Django 本。だが英語だ。
ベストプラクティスが詰まっている本で、Django をイチから順にすべて解説した本ではありません。あと残念ながら対象バージョンが 1.11 ですが、信頼のおける非常に良い本です。

Two Scoops of Django 1.11: Best Practices for the Django Web Framework (English Edition)

Two Scoops of Django 1.11: Best Practices for the Django Web Framework (English Edition)


過去記事でも、この本をオススメしています。興味がある方はこちらもどうぞ。

akiyoko.hatenablog.jp


その他のお役立ちサイト

ブログなどで、Django の信頼できる情報を提供してくれている方々を勝手に紹介します。

narito ブログ

上でも紹介した、narito さんのブログ。かなり広範囲に渡って記事をアップしています。

narito.ninja


okoppe8

Qiita でDjango といえば okoppe8 さんでしょう。かなり信頼できる記事をいくつも書いていて、非常に有用です。

[Django] Heroku デプロイ方法 2018年版 - Qiita
[Django] ファイルアップロード機能の使い方 [基本設定編] - Qiita


Djangoフレームワークのユーザーモデルと認証

tokibito さんのユーザーまわりの機能についてのスライド。非常によくまとめられています。


Django における認証処理実装パターン

認証まわりについての c-bata さんの非常に有用な記事です。脱初級者向けに読んでおいたほうがよいでしょう。

nwpct1.hatenablog.com


Djangoのテストの書き方とCircleCIを活用した継続的インテグレーション

codezine.jp


Django 管理画面逆引きメモ

qiita.com


Django のおすすめライブラリ

qiita.com


最後に

機械学習のおかげか、Python 界隈が非常に盛り上がってきています。Webアプリケーションも Python で一気通貫で作るとなると、Django や Flask、あるいは Tornado や Bottle、Pyramid という選択肢があり、ユーザー認証が必要となると Django が強力な選択肢になります。

「Django が難しい」と感じるのは、フルスタックである Django がカバーしている範囲が大きい(機能がテンコ盛りすぎる)からかと思いきや、そもそも Webアプリ開発の前に知らないといけない知識やスキルが多すぎるというのが原因のひとつであるようにも感じています。つまり、「Django の学習コストが高い」のではなく、「Django に至るまでの Webアプリケーションを含めたスキル全般に対する学習コストが高い」と言えるのではないでしょうか。

この記事では、Django をマスターするために必要な知識やスキルを整理し、その全体像となる学習ロードマップを示してみました。いかがでしたでしょうか? この記事が Django の初学者や初級者の方々のお役に少しでも立てれば幸いです。


学習法ではないかもしれませんが、Django(だけでなくさまざまなプロダクト)を習熟するために一番良い方法は「自分でちょっとしたサービスを作ってみる」だったりします。そういった場合には、チュートリアルを見ながら手を動かして何か作り始め、その延長で自分の作りたいサービスを作ってしまうというパターンがよいかもしれません。

*1:Qiita、はてなブログなど

*2:ProgatePyQなど

*3:Udemyドットインストールpaizaラーニングなど

*4:もくもく会、カンファレンスなど

*5:それでも黒い画面も Git も必要なので、非エンジニアにとってはまだまだハードルは低くないですが。。

*6:チュートリアルとは、基礎的なところから順を追って解説したもので、ひと通り終えることで基本的な操作を学べるようになっています。

*7:django-docs localization

仕事で本格的に Django を使うなら『現場で使える Django の教科書《実践編》』がオススメ!

$
0
0

akiyoko です。

昨年10月の 技術書典5で Django の技術同人誌シリーズの2作目となる新刊 『現場で使える Django の教科書《実践編》』を出してから数ヶ月経ちました。その間、Django 本の読書会をしたり、Amazon で電子版の販売を開始したり、年末のコミケに初参加してサークル「あきよこブログ」として本を再販したりするなど、いろいろとイベントが目白押しでした。

そうやって技術書典5 からの数ヶ月を忙しく過ごしたわけですが、ふと思い返すと私のブログで《実践編》の内容を紹介していなかったことに最近気づいたので、この記事で 『現場で使える Django の教科書《実践編》』の概要と読みどころについて紹介しておきたいと思います。


f:id:akiyoko:20180930140739p:plain:w200

現在、《実践編》の紙の本はオンラインショップの BOOTHで、電子版は Amazon で販売中です。

◆ BOOTH(紙の本)

◆ Amazon(電子版)

 

《実践編》の概要

本書は Python 製の Web アプリケーションフレームワーク「Django(ジャンゴ)」の解説書の第二弾で、Django を本格的に使っている/使おうとしている開発者に向けた本です。開発の現場で必要になる知識、よくある問題へのヒントや解決策を中心に、デプロイやセキュリティ、高速化などさらに実践的な内容にも踏み込んでいます。前作同様、開発現場に必携の一冊にすべく、様々なノウハウをこれでもかと詰め込みました。


《実践編》をひと言で表すと、「基礎のちょっと先に手を伸ばしてみようと考えている開発者に向けたステップアップ本」になっています。前作同様、Django プロジェクトの現場にあると嬉しい一冊になっているはずです。

対象読者

《実践編》の対象読者は、

  • Djang のことをもっと知りたい方
  • 仕事の現場で本格的にDjangoを使いたい方

を想定しています。

Django 公式チュートリアルDjango Girls Tutorialでは物足りなかった方や、実践的な開発に不安のある方にも十分満足できる一冊になっているはずです。そしてもちろん、前作の《基礎編》を読み終えた方にはちょうど良いレベルのステップアップ本になっているでしょう。


なお、Django の基礎(全体像、コンポーネントごとの仕組みや基本的な実装方法など)については説明していません。それらについては、前作《基礎編》でベストプラクティスを交えて詳しく解説しています。


各章の読みどころを紹介

目次


第1章:はじめに
第2章:開発のヒント(認証まわりをサクッと実装)
第3章:開発のヒント(Bootstrap 4 対応)
第4章:開発のヒント(Ajax 対応と JSON レスポンス)
第5章:開発のヒント(ファイルアップロード)
第6章:ユニットテスト
第7章:デプロイ
第8章:セキュリティの TIPS
第9章:高速化のための TIPS
付録A:メール送信の設定
付録B:Let's Encrypt で SSL/TLS 証明書発行


f:id:akiyoko:20180930140511p:plain:w250

f:id:akiyoko:20180930140547p:plain:w250


第2章:開発のヒント(認証まわりをサクッと実装)

Django を使った Webアプリ実装の第一歩として、まず「ユーザー認証まわり」から実装することが多かったりするのではないでしょうか。実は、Django 組み込みの認証システムを使うと、認証まわりの機能をサクッと実装することができます。そのことを知らずに、ログインやパスワード変更といった機能を自前で実装してしまったりするのは「DRY(Don’t repeat yourself)」の原則に反します。しかしながら、認証まわりのノウハウについてまるっと解説した本は(少なくとも日本語の書籍では)ありませんでした。

本章ではまず、最小限の実装でユーザー認証まわりの機能をひと揃えするための具体的な方法について解説をしています。


しかし実際の現場では、サクッと実装しただけでは問題がある場合があります。それは「仕様変更」です。Django デフォルトの認証の仕組みをそのまま利用できる場合はよいのですが、ちょっとカスタマイズしたいとなった場合に難易度が途端に跳ね上がるという点には注意が必要でしょう。たとえば、「ユーザー名ではなくメールアドレスとパスワードで認証できるようにしたい」といったニーズは日常茶飯事に発生します。このような場合にどのように改修すればよいのか、その改修ポイントや具体的なコードを載せています。


本章の最後ではさらに実践的なニーズのひとつである「ソーシャル連携認証」について解説をしています。これを読めば、「OAuth って何?」というレベルの方でも、ソーシャル連携認証の仕組みが分かるようになり、GitHub アカウントでソーシャル認証ログインできる Django サイトが実装できるようになります。

第3章:開発のヒント(Bootstrap 4 対応)

ところで皆さんは「味覇(ウェイパー)」という調味料をご存知ですか?

味覇(ウェイパー) 缶 500g

味覇(ウェイパー) 缶 500g

味覇は中華料理のベースの味付けに「とりあえず使っとけ」という感じで万能・安心・簡単に使える調味料なのですが、「Bootstrap は Webサイトのスタイルを下支えする味覇である」というブログ記事を見て思わず吹き出してしまったことがありました。

さて、業務で Webアプリを作る際、特にプロトタイプを作る段階では Bootstrapなどの CSSフレームワークをとりあえず入れてスタイルを「それ」っぽく整えておくのは常套手段ではないでしょうか。CSSフレームワークはデザインセンスの乏しいエンジニアの強い味方です。

第3章の前半では、Webアプリ開発の初めの一歩として押さえておくべき「Bootstrap 4 の導入方法」について書いています。Django に特化した話はほとんどありません。後半では、「django-bootstrap4」という Django パッケージを使って「Bootstrap 4」の適用をサポートする方法について解説しています。

第4章:開発のヒント(Ajax 対応と JSON レスポンス)

Django のビューでは通常のレスポンス以外に、JSONレスポンスを返すことができます。テンプレートの JavaScript から Ajax リクエストを送信して JSONレスポンスを受け取ることで画⾯全体を更新せずに⼀部の部品だけを書き換えることができるため、これを利用することで UI・UX のよい Web画面を制作することができます。

なお、Django から JSON を返す⼿段としては、「Django REST framework」と呼ばれる有名なパッケージを使う⽅法があります。REST でリクエストをしてJSON で受け取るような SPA やアプリのバックエンドとしてよく利⽤されています。しかしこの章で紹介する⽅法によって、Django REST framework を使わなくても簡単に JSON レスポンスが返せることがお分かりいただけると思います。

なお、JavaScript で Django に Ajaxリクエストを送信する際、またビューから JSONレスポンスを返す際にそれぞれちょっとした注意点があります。第4章の中盤ではそれらの注意点について具体的なコード例を交えて解説をしています。

章の終盤では、AjaxとJSONレスポンスを応用すればこんなアプリが作れるぞ!というちょっとしたアプリのコードを紹介しています。時系列データを保持した pandasDataFrameを JSONレスポンスとして返し、テンプレート側では「Tabulator」という JavaScript のライブラリを利⽤して JSON を処理するというサンプルになっています。はっきり言って、ポエムです。

f:id:akiyoko:20181021163655p:plain:w450

第5章:開発のヒント(ファイルアップロード)

Django では、静的ファイルのうち、システム管理者を含めたユーザーが Webアプリケーションを利⽤してアップロードする CSV や PDF、画像などのファイルを「メディアファイル」と呼んでいます。

前作《基礎編》では「STATIC_ROOT」「STATICFILES_DIRS」「STATIC_URL」などの静的ファイル関連の設定について詳しく説明しましたが、本作では、メディアファイル(およびファイルアップロード)について、設定から実装、注意点に至るまで詳しく解説しています。

少し発展的な内容として、「django-storages」を使ってクラウドストレージにファイルアップロードする方法とその設定について記載しています。そのほか、ファイルアップロードを利用する際に便利に使える Django パッケージをいくつか紹介しています。

章の最後は、不正なファイルがアップロードされないためのセキュリティ対策について。ユーザーがアップロードしたファイルを他のユーザーに配信する場合は、ファイルの不正チェックが必須になるでしょう。

Django の最もハマりがちなポイントといえば「静的ファイル」でしょう。メディアファイルは静的ファイルと混同しやすく、ファイルアップロードの実装は簡単ですが仕様に少し癖があります。業務用 Webアプリではよく利用されるので一度全体を整理して把握しておきたいところです。

第6章:ユニットテスト

動くコードも大事ですが、現場においてはテストも同じくらい重要です。 Django では、以下に示すようなユニットテストのサポートが最初から用意されており、非常に充実しています。

  • test コマンド
  • テストランナー
  • 標準の unittest.case.TestCase を継承した Django の TestCase クラス
  • Webテストクライアント

Django のユニットテストで押さえておくべき知識は、次の3点です。

  • ① 慣例と命名ルール
  • ② TestCase における各種メソッドの実行フロー
  • ③ テストの実行方法

まず、慣例と命名ルールを押さえておかないと、テストランナーが自動で収集してくれなくなります。次に、Python 標準の unittest.case.TestCase を継承した TestCase には、テスト用のデータベース作成および削除、フィクスチャと呼ばれるファイルからのテストデータ生成、登録および変更したテストデータのロールバックなどの機能が追加されています。それらを含めた各種メソッドの実行フローや拡張ポイントを把握しないと、効率の良いテストケースを書くことはできません。Django 標準のユニットテストは test コマンドから実行できますが、その実行方法についても押さえておく必要があるでしょう。

また、多くのプロジェクトでは Coverage.pyを導入してカバレッジを計測します。カバレッジ・レポートを品質指標として利用できるほか、実際に実行されたコード行を可視化することでテストケースに抜け漏れがないか、あるいはテスト条件や実装方法に誤りがなかったかどうかを把握できるといったメリットもあります。

第7章:デプロイ

「デプロイ」とは、実際に利用する環境に Webアプリを配備(deployment)して、ユーザーから利用できる状態にすることを指します。特に、本番環境へのデプロイは「本番デプロイ」などと呼ばれます。

デプロイの工程には、サーバの調達から必要なソフトウェアのインストールやその設定、データベースの構築や初期データの投⼊、セキュリティの設定など、ありとあらゆる作業が含まれます。本章では、インフラエンジニアでない⽅にもできるだけ分かりやすいように、デプロイ⼿順を最初から最後まで一気通貫に説明していきます。具体的には、サーバに乗り込むための鍵ペアの作成から Let's encrypt による常時 SSL化の設定まで、かなーり詳しく書いています。全部で44ページ! 世界で一番詳しい Django のデプロイ解説書を目指しました。

本章で構築するサーバ構成は、サーバ1台でリバースプロキシサーバ、アプリケーションサーバ、データベース、ファイルサーバなど全てをまかなうオールインワン構成です。シンプルで安上がりになる反⾯、可⽤性(冗⻑化)やスケールを考慮していない点には注意が必要です。

  • サービス: DigitalOcean(クラウド)
  • OS: Ubuntu 18.04
  • サービスマネージャ: systemd
  • データベース: MySQL 8.0 (またはPostgreSQL 10.5)
  • リバースプロキシサーバ: Nginx 1.14
  • WSGI サーバ: Gunicorn 19.9
  • Python: 3.6.5
  • Django: 2.1

なお、各ソフトウェアのバージョンはできる限り最新のものを利用しています。

第8章:セキュリティの TIPS

前章では本番デプロイについて書きましたが、本番公開時にどうしても気になるのがセキュリティの問題ですよね。いざ本番リリースしようとしたときに「これって公開しちゃって大丈夫なの?」と怖くなってしまうことはないでしょうか?

Djangoはフルスタック(全部入り)が大きな特徴のひとつですが、セキュリティ対策もその中にちゃんと含まれています。ただし、「適切に利用していれば」という条件付きです。というわけで、本章の前半は Django が提供しているセキュリティ対策についてのおさらいです。後半では、本番デプロイを想定したオリジナルの「セキュリティ・チェックリスト」を用意しました。ぜひ本番リリース時にお役立てください。

第9章:高速化のための TIPS

「Django は遅い」なんてもう言わせない!

最終章の9章では、簡単に実現できる高速化の具体策について解説しています。前章で説明したようにセキュリティまで「全部入り」の Django は悪く言えば重厚長大で、パフォーマンスは二の次であると言わざるを得ません。

ここで高速化の対策として解説しているのは二点です。一点目は、データベースのクエリ実行について。特定の画面のレスポンスが異常に遅い場合、クエリ実行に問題がある(クエリの本数が想定以上に多くなってしまう、いわゆる「N+1」問題が発生している)場合がありますが、その対策について解説します。二点目は、Django にデフォルトで含まれている「キャッシュ」機能について、その使いどころをいくつか具体的に挙げています。アプリ次第では劇的に応答時間が短くなることもあるでしょう。


《実践編》の評価

SNS やブログ上での『現場で使える Django の教科書《実践編》』の評価を勝手に掲載させていただきます。


ks6088ts.github.io


まとめ

おかげさまで、前作の Django の技術同人誌『現場で使える Django の教科書《基礎編》』は まだまだ販売好調で、販売累計数は 2,500冊を超えています。こちらも Django プロジェクトの現場にあると嬉しい一冊ではありますが、どちらかというと、現場に入った新規参画者や新人に読んでほしい初心者・初級者向けの一冊になっていると思います。


◆『現場で使える Django の教科書《基礎編》』Amazon(電子版/ペーパーバック版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》



基礎編を読み終えて、仕事でもっと本格的に使っていこうと考えているなら、今回紹介した『現場で使える Django の教科書《実践編》』が絶対オススメです。何かで詰まって半日無駄にするくらいなら、《実践編》を一冊買う方が絶対安いです。きっと役に立つ情報がたくさん載っていると思います。特に、デプロイや高速化、セキュリティ、認証、ユニットテストに関しては、これほどまとまった情報を提供しているところは他にはまだないと自負しています。

気になった方はこの機会に《実践編》をぜひどうぞ。


f:id:akiyoko:20190120144009p:plain


なお、紙の本で『現場で使える Django の教科書』シリーズの二冊(基礎編・実践編)をお得に手に入れたいという方には、BOOTH での二冊セット販売も用意しています。

booth.pm


技術書典6 で『現場で使える Django REST Framework の薄い本』を頒布します

$
0
0

akiyoko です。

本日いよいよ「技術書典6」が開催されますね。私は今回も「あきよこブログ」としてサークル参加します。これで3回連続3回目のサークル参加になります。

f:id:akiyoko:20190413231539p:plain:w400


過去2回で2冊の「Django の薄い本」を出してきましたが、今回の新刊も Django 関連本です。『現場で使える Django REST Framework の薄い本』というタイトルからお分かりの通り、「Django REST Framework(通称「DRF」)」に関する技術同人誌です。

Django REST Framework(DRF)って何?

「Django」は Python で Webアプリケーションを作成するためのフレームワークで、Webアプリケーションを作成する際に必要となるコンポーネント(部品)や API を多数提供しています。Django は多数の機能を提供しているものの、REST API バックエンド(REST API を提供する Webアプリケーション)を構築する際のさまざまなニーズに応えるには少し機能が足りず、いろいろと自前で実装しなければいけません。

そこで登場したのが、「Django REST Framework」(以降「DRF」と表記)です。DRF は、REST API バックエンドを構築することに特化したサードパーティ製の Django パッケージで、REST API を提供する際に必要となる機能や便利な機能を補完・拡充してくれる拡張パックのような役割を果たします。実際のプロジェクトでは、Webアプリケーションのベースとなる機能は Django を利用し、REST API に特化した機能は DRF を利用する、といった使い方をします。


f:id:akiyoko:20190413224931p:plain:w500

DRF 本を書いた理由

かく言う私も現在仕事で「DRF」を使っており、仕事の現場においては「素の Django」よりも「DRF」の方が使われているようにも感じています。しかしながら、DRF に関する日本語情報は Django よりも圧倒的に不足しています。日本語書籍については現在どこを探しても見つかりません。商業誌を待っていてもあと何年かは出ないだろうから、もし技術書典6に当選したら30ページくらいの本当に薄い本を書いてみようかなと思い立ったのが昨年末。これが地獄の始まりでした。。

それからどうなったか?

技術書典4から3回連続で技術同人誌を頒布していますが、今回が一番辛かったです。昨年末あたりから執筆のための調査を始めていて実質的な執筆は2月から開始したのですが、あれよあれよという間に30ページが50ページになり、70ページになり、最終的には表紙を含めて128ページの「薄くない本」に仕上がってしまったのでした。

毎回執筆内容を Git で管理していて今回からコミットコメントに執筆時間を加えることにしてみたのですが、今回の合計執筆時間は333時間になりました(会場価格は1,000円なので私の作業1時間あたり「3円」で買えてしまうということですね・・)。内容には満足しているものの、3月は生活のすべてを投げ打って執筆に没頭してしまいました。ご迷惑をお掛けした関係各所の皆さま、本当に申し訳ありませんでした。最後に、家族のサポートがなければこの本は世に出ていなかったということも付け加えさせてください。

どんな内容?

Django REST Framework(DRF)を現場で使う際に必要となる基礎知識についてまとめた技術同人誌で、本文124ページ、まるまる「Django REST Framework」に関する本です。なお、DRF は Django をベースにしている部分があるので Django についての解説は要所要所で書いているものの、Python についての解説は一切ありませんのでご注意ください。

前半は DRF の概要や全体像、コンポーネントごとの仕組みや使い方、セキュリティや認証などの基礎知識を座学で進めていきます。後半はチュートリアルおよび発展的な Tips という構成になっています。

後半のチュートリアルでは、Django も Django REST Framework も何にも分からないという方でもちょっとした SPA が作れるように、Django REST Framework と Vue.js を使った SPA のサンプルプロジェクトを2つ、簡単なものと少し難しめなものを用意しました。これを手本に写経すれば、REST API を使った Webアプリケーションの仕組みが何となく掴めるでしょう。


レビュアーとして、くろのて勉強会を主催をしている @crohacoさんにもご協力いただいたのですが、@crohaco さんからお墨付きをいただけました。DRF の勉強会ではお世話になりました。そしてレビューありがとうございました。

そのほか、Django 系イベントでいつも会う @kaizumakiさんや u1 さんにもレビューをしていただきました。ありがとうございました!

対象読者

対象読者としては、

  • Django は何となく分かるが、Django REST Framework は初めてという方
  • Django REST Framework のまとまった日本語情報を手に入れたい方
  • Django REST Framework + Vue.js で SPA を構築したい方
  • 現場で本格的に Django REST Framework を使いたい方

を想定しています。

最低限必要の知識としては「Django の仕組みが何となく理解できていること」です。Django 公式チュートリアルDjango Girls チュートリアルをひと通り終えたくらいであれば、何とか理解できるレベルになっているかと思います。拙著『現場で使える Django の教科書《基礎編》』を読み終えたくらいの知識があれば万全ですが、『現場で使える Django の教科書《実践編》』レベルの知識は不要でしょう。


現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《実践編》

現場で使える Django の教科書《実践編》


目次

気になる目次は ↓ のようになっています。


はじめに
第1章: Django REST Framework(DRF)の概要
第2章: モデル・シリアライザ・ビュー・URLconf の基本的な使い方
第3章: DRF とセキュリティ
第4章: DRF と認証
第5章: チュートリアル その1: DRF + CDN 版 Vue.js で Cookie 認証付き SPA をスピード構築
第6章: チュートリアル その2: DRF + Vue CLI 3 で JWT 認証付き SPA を本格構築
第7章: 現場で使える Tips 集
おわりに

f:id:akiyoko:20190413231404p:plain:w300


頒布本情報

当日のお品書きを作りました。
お釣りがなるべく出ないように考慮した「会場特別価格」です。

f:id:akiyoko:20190413231539p:plain:w400



あと、既刊の『現場で使える Django の教科書《基礎編》』『現場で使える Django の教科書《実践編》』も持っていきます。

f:id:akiyoko:20190413231654p:plain:w400

f:id:akiyoko:20190413231728p:plain:w400

これらの既刊については、Amazon や BOOTH で電子版とペーパー版が絶賛販売中です。


◆ 現場で使える Django の教科書《基礎編》 - Amazon(電子版・ペーパー版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

◆ 現場で使える Django の教科書《実践編》 - Amazon(電子版)

現場で使える Django の教科書《実践編》

現場で使える Django の教科書《実践編》

◆ 現場で使える Django の教科書《実践編》 - BOOTH(ペーパー版)
現場で使える Django の教科書《実践編》【紙の本】(技術書典5バージョン) - あきよこブログ(akiyoko - BOOTH

頒布場所

頒布場所は「か63」の「あきよこブログ」です。
見本誌を置いてますので、立ち読みだけでもお気軽にどうぞ。

f:id:akiyoko:20190413232620p:plain

池袋サンシャインシティ2F、4/14(日) 11時オープンです。今回は、会場2時間は有料入場券(1,000円)が必要になっています。それでも午前中は混雑すると思いますのでご注意ください。

なお勝手ながら、当日13時までの有料入場者特典として、弊ブースにて『現場で使えるDjangoの教科書《実践編》』(紙の本)を会場特別価格からさらに500円引きさせていただきます(1,500円→1,000円)。(後払いアプリだと対応できないかもしれないので)現金払いのみでの割引とさせてください。



最後に

ウチの奥さんに「そんなに寝てないと死ぬよ?」と何度も言われながら、ようやく今週の火曜にすべり込み入稿できました。表紙がモノクロだったので標準価格からのアップは免れましたが、カラーだったらアウトというギリギリっぷりでした。そんな感じで今回の執筆で気力体力ともに尽き果てました。今日の技術書典が終わったら昇天しているかもしれません。。

DjangoCongress JP 2019 で「現場で使える Django のセキュリティ対策」というタイトルで登壇してきました

$
0
0

akiyoko です。

昨日の DjangoCongress JP 2019(Day 1 カンファレンスデー)で「現場で使える Django のセキュリティ対策」というタイトルで登壇してきました。その報告です。


発表資料は こちらにアップしています。


発表の動機

仕事の現場でもっと Django を使ってほしいという想いから、この発表を思い立ちました。Django 普及の突破口のひとつとして、まずはセキュリティの懸念を取り払うことが重要なのでは?と考えたのです。

Python が企業でも幅広く使われるようになったことや書籍が充実し始めたことで、日本でもようやく Django が注目されるようになりました。4月に待望のバージョン2系の LTS がリリースされ、ますます現場で Django が盛り上がることが予想されますが、導入検討の際にネックになるもののひとつに「セキュリティ」への懸念があります。私は現在、ある Django プロジェクトの立ち上げに携わっているのですが、そこで実際によく言われたのが「Django ってセキュリティ的にどうなん?」でした。日本では(特に SIer 界隈では)Django がまだあまり知られていないので、そのような疑問が出てくるのは当然といえば当然かもしれません。

一方の開発者からすると、フルスタック(全部入り)の Django にはデフォルトでセキュリティ対策も含まれていますが、そのあたりの理解が中途半端だと、リリースした Webアプリケーションが悪意ある攻撃者の格好の餌食になってしまいかねません。そうならないためにも、Django のセキュリティ事情については開発前から(もちろん開発中でも)きちんと把握しておきたいところです。

そこで今回、IPA(情報処理推進機構)が注意喚起情報として公表している「安全なウェブサイトの作り方」という冊子にまとめられた代表的な脆弱性の概要と、それらの脆弱性に対して Django では具体的にどのような対策をしているのかについて解説することにしました。これによって発注側企業においてはセキュリティの懸念が払拭され、一方の開発側企業においてはセキュリティ施策のヒントとして活用されることを期待しています。

対象者

対象者は、Django の導入を検討している方、および Django を使った Webアプリケーション開発者を想定しています。なお、Django 初級者の方にも十分理解できる内容になっていると思います。

Webアプリケーションの基本的な知識(特に Cookie を使ったセッション管理や HTTPヘッダなどの知識)があれば、セキュリティの知識についてはほぼゼロ(用語を何となく聞いたことがあるレベル)でも問題ありません。CSRF などの重要な、そして重要な割にあまりよく理解されていないものについては、「CSRF(しーさーふ)って何?」というレベルの人にも分かるように基本から解説しています。

ポイント

メインの話題として

① Webアプリケーションのセキュリティ対策って
そもそも必要なの?
② 「これだけは絶対やっとけ」的な基準はある?
③ フルスタック(全部入り)の Django を使えば
セキュリティ対策もまるっと万事解決?

の三点について話しました。
詳細についてはスライドをご覧ください。

発表の準備

昨年の LTでド緊張して失敗した苦い思い出があるので、今回はまず、心構えから入りました。事前に読んだのは、たまたま見つけた オリラジ中田さんの講演会ログです。要約すると、プレゼンでは「カンペを読まない」「言い訳しない」「練習をサボらない」の3つのタブーがあるということです。中でも、人前で練習をすることが「練習」でそれ以外は「練習」ではないというのはまさにその通りだと思い、リハーサルをなるべく多くこなそうと考えていました。

発表の内容については CFP を出した頃に目次レベルまで固めていたのですが、実際に発表資料を準備し始めたのは仕事の関係もあって GW の終盤からとなりました。しかしこれはちょっと遅すぎました。資料が完成したのは本番5日前。そこから2回、会社の Django 経験者やコンサルタントのメンバーの前、そして現プロジェクトメンバーの前でのリハーサルをおこないました。メンバーからのフィードバック、そして自身の反省から、資料がブラッシュアップされていき、話した方がよいこと・話さなくてよいことが明確になり、想定問答も明らかになって私にとっては良いこと尽くめでした。もっとリハーサルをしたかったのですが、何度も集まってもらうのもメンバーの負担になるのと、直前にフィードバックをもらっても反映できない、余計に混乱してしまうと感じたので、これが限界だったのかも知れません。あとはブツブツ独り言を繰り返し、本番の流れをイメージしていきました。


フィードバックの中で、「図を指差しで説明するよりもレーザーポインターでやった方がいい」と言われて急遽買ったのがこれ。パワポのページ送りもできます。本番前日の夕方に届きました。しかしこれが、当日あのような事件を引き起こすことになろうとは。。


あと、GW 中盤に引いた風邪がずっと長引いていたので体調を整えるために前日夜にマッサージに行ったのですが、強かったのか余計に首を痛めてしまいました。


発表はどうだった?

「発表前にやることリスト」を作っていたので、それを淡々とこなすことで緊張はギリギリのところで抑えられていました。

しかし、プレゼン開始直後に事件が起きました。前日の動作チェックでは問題なかったレーザーポインターがページ送りができなくなり、直前に使用を諦めました。これで緊張のコップから水が少し溢れてしまいました。。


f:id:akiyoko:20190519130935p:plain:w180

この事件がきっかけとなって冒頭の10分はガチガチでした。途中からあきらめの境地に至ってから割と話せるようになったと思いますが、そこで何とか踏み止まれたのも事前のリハーサルのおかげです。あれが無ければもうボロボロの結果になったに違いありません。協力してくださった皆さん、本当にありがとうございました。



質問

想定よりも時間がかかってしまいましたが、発表は42分頃に終わりました。そこで出た質問について補足します。

Q.{% csrf_token %}タグを入れ忘れてしまうのを防ぐ方法はないのか?

POST リクエストを送信する form 要素に {% csrf_token %}タグを入れ忘れると、403 エラーが出ます。しかしながら、CsrfViewMiddleware を無効にするなり @csrf_exempt デコレータを利用したりすると、CSRF 検証はされずに脆弱性が露呈してしまいます。会場では、設定ファイルのセキュリティチェックをしてくれる「python manage.py check --deploy」を実行すれば CsrfViewMiddleware が無効化されていることをチェックできるかも知れないと回答しましたが、それを改めて検証してみました。

実際に CsrfViewMiddleware を「MIDDLEWARE」からコメントアウトして check コマンドを実行すると、期待通りに CsrfViewMiddleware が無効化されているという警告が出ました。

(venv) $ python manage.py check --deploy
...(略)...
?: (security.W003) You don't appear to be using Django's built-in cross-site request forgery protection via the middleware ('django.middleware.csrf.CsrfViewMiddleware' is not in your MIDDLEWARE). Enabling the middleware is the safest approach to ensure you don't leave any holes.


いい感じですね。


反響

いろいろと反響をいただきましたが、一番驚いたのがこれです。


あの徳丸さんにTweetしてもろた!😲マジか!

徳丸さんは、私の発表でも紹介した Webアプリのセキュリティ対策の金字塔「徳丸本」こと『体系的に学ぶ 安全なWebアプリケーションの作り方 第2版』の著者です。現場でも必読書になっています。



あと夕方頃に気付いたのがこちら。Speaker Deck のスライド資料が、はてなブックマークのホットエントリーに入っていたみたいです。


最後に

今年の DjangoCongress JP 2019(Day 1 カンファレンスデー)はセッションもパーティーも大盛況で、大御所イベントのような安定感がありました。これも、ずっと前からこの日のために動いてくれていたスタッフの皆さんの準備、運営、そして情熱のおかげです。本当にありがとうございました。昨年も参加させていただき、そして今年はセッション発表の機会をいただいて、このような素晴らしい場で発表側に回れたことは大変光栄に感じています。おかげさまで昨年のリベンジもできました。またたくさんの方にセッションを聴きにくださり、嬉しくそして心強かったです。機会があれば来年もチャレンジしてみたいと思います。



DRF を使うなら必読!『現場で使える Django REST Framework の教科書』を技術書典7 で頒布します

$
0
0

9月22日に開催される 技術書典7に、「あきよこブログ」として 4回目のサークル参加をします。

みなさん安心してください、今回も Django 本ですよ 😁


新刊は『現場で使える Django REST Framework の教科書』です。


f:id:akiyoko:20190908041824p:plain:w400


「Django REST Framework(通称 DRF)」にピンと来ない方がいるかもしれませんが、「Django」の上に乗っかった、API を作ることに特化したライブラリです。つまり DRF は、Python で REST API を作るためのフレームワークです。SPA(シングルページアプリケーション)やスマホアプリのバックエンドとして利用されることが多いです。Django も DRF も日本ではあまり知られていませんが、実は海外では結構有名です。

どんな内容?

技術書典6 で頒布した前作『現場で使える Django REST Framework の薄い本』にかなり大幅な加筆・改訂を加えて、「Django の教科書」シリーズとしてリニューアルしました。前作の124ページに対して、今作は204ページと大ボリュームの仕上がりになっています。

今のところ、同人誌を含めて 日本でオンリーワンの「Django REST Framework」の日本語書籍になっています。

内容は、Django REST Framework を現場で使う際に必要となる基礎知識と発展的な Tips をまとめたものになっています。なお、Django REST Framework は Django をベースにしている部分があるので、Django についての解説に紙面を割いているところもあります。

前半は DRF の概要や全体像、コンポーネントごとの仕組みや使い方、セキュリティや認証などの基礎知識を座学で進めていきます。後半はチュートリアルおよび発展的な Tips という構成になっています。

後半のチュートリアルでは、Django も Django REST Framework も何にも分からないという方でもちょっとした SPA が作れるように、Django REST Framework と Vue.js を使った SPA のサンプルプロジェクトを2つ、簡単なものと少し難しめなものを用意しました。これを手本に写経すれば、REST API を使った Webアプリケーションの仕組みが何となく掴めるでしょう。

目次

f:id:akiyoko:20190907201801p:plain:w500
f:id:akiyoko:20190908101706p:plain:w500

対象読者

対象読者としては、

  • Django は何となく分かるが、Django REST Framework は初めてという方
  • Django REST Framework のまとまった日本語情報を手に入れたい方
  • Django REST Framework + Vue.js で SPA を構築したい方
  • 現場で本格的に Django REST Framework を使いたい方

を想定しています。

最低限必要の知識としては「Django の仕組みが何となく理解できていること」です。Django 公式チュートリアルDjango Girls チュートリアルをひと通り終えたくらいであれば、何とか理解できるレベルになっているかと思います。拙著『現場で使える Django の教科書《基礎編》』を読み終えたくらいの知識があれば万全ですが、『現場で使える Django の教科書《実践編》』レベルの知識は不要でしょう。


前作の薄い本と何が違うの?

ざっと挙げるとこんな違いがあります。

  • 本文が204ページに大幅増(前作の124ページから1.6倍!)
  • DRF のコンポーネントの解説が充実
  • ユニットテストの章を新設
  • Tips(発展編)のトピック数が 5 ⇒ 13 に(ページ数は 11p ⇒ 31p)
  • 各種ライブラリは最新バージョンに対応

一番の特徴は、コンポーネントの解説を充実させたことです。「モデル・シリアライザ・ビュー・URLconf」で1つの章になっていたのを、それぞれ独立した章として新設しました。ページ数では、モデル 1p ⇒ 18p、シリアライザ 8p ⇒ 18p、ビュー 14p ⇒ 25p、URLconf 5p ⇒ 8p とそれぞれ大幅に増えています。特に、シリアライザは DRF の中でも大きな部分を占めるので、図を増やしてイチから分かりやすい解説を目指しました。

あとは、Django 初心者に少し優しくなりました。特に、前作ではモデルについての説明を「Django と同じ。以上!」としていたのを、きちんと章立てをして解説しています。内容は『現場で使える Django の教科書《基礎編》』からのほぼ抜粋になりますが、スッキリとまとめ直した上で DRF 向けに修正を加えています。

全体としては、加筆を120ページほどおこなっています。



そして、「そこまで言われても、前作の薄い本買っちゃったしなぁ。どうしよう・・」と悩んでいるあなたに朗報です。

前作『~の薄い本』を技術書典7に持ってきていただいた方、先着50名に、なんとワンコイン(500円)で新刊を買えるサービスを実施します!


f:id:akiyoko:20190908122859p:plain:w400

ただし、お一人様1冊限りでお願いします(薄い本にはスタンプを押させていただきますのでご了承ください)。


頒布本情報

既刊の『現場で使える Django の教科書《基礎編》』『現場で使える Django の教科書《実践編》』を含めて、「Django の教科書」シリーズが3冊揃っています。

なおいつものように「会場特別価格」です。


f:id:akiyoko:20190917121916p:plain:w300


f:id:akiyoko:20190917121947p:plain:w300


実は今回の技術書典に合わせて《実践編》を1年振りにリニューアルして、Django 2.2 対応等をおこないました。


これらの既刊については、Amazon や BOOTH で電子版とペーパー版が販売中です。


◆ 現場で使える Django の教科書《基礎編》 - Amazon(電子版・ペーパー版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

◆ 現場で使える Django の教科書《基礎編》 - BOOTH(ペーパー版)
現場で使える Django の教科書《基礎編》【紙の本】 - あきよこブログ(akiyoko blog) - BOOTH


◆ 現場で使える Django の教科書《実践編》 - Amazon(電子版)

現場で使える Django の教科書《実践編》

現場で使える Django の教科書《実践編》

◆ 現場で使える Django の教科書《実践編》 - BOOTH(ペーパー版)
現場で使える Django の教科書《実践編》【紙の本】(技術書典6バージョン) - あきよこブログ(akiyoko - BOOTH



頒布場所

日時は 9/22(日)11時から17時まで、頒布場所は池袋サンシャインシティ3F 展示ホール「お74C」の「あきよこブログ」です。

見本誌を置いてますので、立ち読みだけでもお気軽にどうぞ。

f:id:akiyoko:20190917122645p:plain



最後に

余裕をもって始めたはずの執筆ですが、急遽、《実践編》の改訂と増版をしたのもあり、今回もギリギリの入稿になってしまいました。出すものは全部出した感があるので、自分なりにスッキリしています。技術書典当日は晴れやかに迎えられそうです!

PyCharm で Django の開発をするなら絶対やっておくべき便利な設定

$
0
0

この投稿は 「Django Advent Calendar 2019 - Qiita」 6日目の記事です。

Python 開発の IDE には「PyCharm」を激推ししている akiyoko です。
推しの理由は、以下の点が非常に有用だと感じているからです(JetBrains のステマじゃないですよん 😅)。

  • インストールしたそのままの状態で快適に使える
  • venv」(仮想環境を作成するためのモジュール)や「pip」(パッケージ管理ツール)のコマンドの使い方が分からなくても、画面からポチポチと操作できる
  • コードジャンプ機能と自動整形機能を使うことで開発効率が著しく向上する
  • デバッグ実行を使うことでコード解析が捗る


中でもデバッグ実行が便利ですよね。ライブラリの中もどんどん潜ってデバッグ実行できるので、障害解析やコードの理解が格段に捗ります。


Django の開発をする際にももちろん PyCharm を愛用しています。プライベートでは有償版の PyCharm Professional Edition を利用していますが、仕事では無償版の PyCharm CE(Community Edition)を利用しています。



PyCharm の開発元 JetBrains の 昨年の調査によると、Webアプリ開発をするときは 30〜40%くらいの方が PyCharm(有償版・無償版を合わせて)を利用しているとのこと。私の周りのつよつよ Pythonista の方でも PyCharm を愛用している人は多いです。

この記事を書くにあたって事前に統合開発環境(IDE)の利用状況をアンケートしてみたのですが、

PyCharm の利用率が 30〜40%なのは JetBrains の調査と概ね合致します。
それにしても、VS Code の勢いがすごいですね!
Webアプリ開発ではフロントエンドまわりの面倒も見なくてはいけないことが多々あるので、JS まわりのサポートが弱い PyCharm CE(無償版)よりも、VS Code が選ばれるという状況があるのかなと感じました。皆さま、アンケートにご協力ありがとうございました 🙇‍♂️



前置きが長くなりましたが、ここから本題です。

有償版・無償版を問わず、PyCharm を利用して Django プロジェクトの開発をするなら「これだけはぜひ設定しておいてほしい」という便利な設定があります。


それは、「runserver」の実行(Run / Debug)設定です。



この設定をすることで、

  • ワンクリックで runserver のデバッグ実行が可能
  • runserver の実行で PyCharm のターミナルツールウィンドウを専有しない

というメリットが得られます。



runserver の実行(Run / Debug)設定

では、その設定方法です。*1


Django プロジェクトのひな型を作成する際に「startproject」コマンドを実行すると、管理コマンドを実行するための「manage.py」が自動生成されますよね。

その「manage.py」を右クリックし、「Create 'manage' ...」を選択します。なお、すでにこのプロジェクトで Run / Debug 設定をしたことがある場合は「manage.py」の右クリック時にこの選択肢が表示されないのでご注意ください(その場合は「Run」>「Edit Configurations...」メニューから Run / Debug の設定をおこなってください)。

f:id:akiyoko:20191203080923p:plain

Run / Debug 設定画面が表示されるので、「Parameters」に「runserver」と入力して、「OK」をクリックします。この際、「Name」には、分かりやすいようにたとえば「runserver」と入力しておけばよいでしょう。

f:id:akiyoko:20191203080931p:plain:w500

Run / Debug 設定を済ませると、ナビゲーションバーの右側に「runserver」との表示がされます。

f:id:akiyoko:20191203080957p:plain

「runserver」の右側の虫アイコンをクリックすればデバッグ実行が開始されます。

f:id:akiyoko:20191203081003p:plain:w400


デバッグ実行を開始すると、デバッグツールウィンドウ(Debug タブ)が起動してコンソールにログが出力されます。コードの途中にブレークポイントを置いておけば、コードが実行されたときにそこで中断されて変数などがデバッグができるようになります。

f:id:akiyoko:20191204003907p:plain


デバッグツールウィンドウの使い方については、公式ヘルプの「デバッグツールウィンドウ - ヘルプ | PyCharm」を参照してください。



いつもなら runserver を実行するのに

> python manage.py runserver

というコマンドをターミナルツールウィンドウ(Terminal タブ)を使って実行するところを、デバッグ実行はそれとは別のデバッグツールウィンドウ(Debug タブ)上で動作するため、ターミナルのウィンドウを専有することがありません。このため、makemigration、migrate、createsuperuser などの管理コマンドを実行するために、わざわざターミナル上で実行している runserver を停止して、その後 runserver を再実行する・・なんてことをする手間が不要になるのです。


これは便利ですよね〜 😚




おまけ ①

ここで、便利な裏技(?)をひとつ紹介します。

デバッグ実行中にブレークポイントでコードの実行を止めた状態ではデバッグツールウィンドウに「Debugger(デバッガ)」と「Console(コンソール)」という2つのタブが表示されます。ここで、「Console」タブをクリックして、Python ロゴのアイコン(Show Python Prompt)をクリックしてみてください。


f:id:akiyoko:20191205033219p:plain:w550


すると、任意の Python コードが、止めたコード内で実行できるようになります。
ハイ、便利〜 😆


おまけ ②

runserver 実行時にオプションを指定したい場合がありますよね。

そんな場合は、ナビゲーションバー右側の「runserver」をクリックし、「Edit Configurations...」を選択して Run / Debug の設定画面を開きます(「Run」>「Edit Configurations...」メニューからでも開くことができます)。

f:id:akiyoko:20191205041253p:plain:w500


「Parameters」に設定している「runserver」のところを「runserver --settings xxx」などと書き換えることで、実行時のオプションが指定可能です。

f:id:akiyoko:20191205041641p:plain

また、「Environment variables」から「DJANGO_SETTINGS_MODULE」などの環境変数を設定することも可能です。


おまけ ③

runserver の他によく利用する Django の管理コマンドとして、「test」(ユニットテストの実行)があります。

今回紹介した runserver の実行設定と同じようにワンクリックで Django プロジェクトのユニットテストを実行したい場合は、次のように「runserver」の設定をコピーするのが簡単です。

コピーしたら、「Parameters」を「test」に書き換えます(「Name」も適宜「test」などと書き換えます)。

f:id:akiyoko:20191205041944p:plain


あとは、「Run」アイコンか「Debug」アイコンをクリックするだけで Django プロジェクトのユニットテストが実行できるようになります。

f:id:akiyoko:20191205043241p:plain:w500



おまけ ④

ここまでくると、Coverage.py を利用したカバレッジもワンクリックで実行したいですよね。

こんな感じで Run / Debug 設定をすれば OK です。

f:id:akiyoko:20191205042003p:plain

f:id:akiyoko:20191205042020p:plain

ポイントは、「Script path」のところを「Module name」に変更してから、「coverage」と手入力するところですかね(仮想環境下にインストールされた coverage の絶対パスを「Script path」に指定してもよいですが)。もちろん、pip で coverage をインストールしておいてくださいね。

ちなみに、有償版の PyCharm Professional では、PyCharm に内蔵された独自のカバレッジ機能を使ってワンクリックでカバレッジを取得することができます。*2



まとめ

PyCharm で Django の開発をするなら、runserver の実行(Run / Debug)設定をやっておきましょう。

  1. 「manage.py」を右クリックして「Create 'manage' ...」を選択
  2. Run / Debug 設定画面で「Parameters」に「runserver」と入力して「OK」

これだけです。ほんの5分足らず(もしかしたら1分くらいで??)で設定は終わります。

runserver のデバッグ実行をポチッとワンクリック(ショートカットもあります)でスタートできる便利さを味わうと、もう PyCharm から離れられませんよ〜 😙


Enjoy Django & PyCharm !! 😉


f:id:akiyoko:20191206074253p:plain




明日は、nogisshさんの「Django Advent Calendar 2019 - Qiita」7日目の記事です。よろしくお願いします。



宣伝

Django の本を3冊書きました。Django 開発のお供にどうぞ。

現場で使える Django の教科書《基礎編》

Amazon(電子版/ペーパー版)

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

BOOTH(ペーパー版)

現場で使える Django の教科書《実践編》

Amazon(電子版)

現場で使える Django の教科書《実践編》

現場で使える Django の教科書《実践編》

BOOTH(ペーパー版)

現場で使える Django REST Framework の教科書

Amazon(電子版)

BOOTH(ペーパー版)

*1:PyCharm のバージョンは Community Edition(無償版)の「2019.3」(現時点での最新バージョン)です。

*2:ビルトイン開発者用ツール - 機能 | PyCharm

Django モデルのフィールドの「auto_now_add」「auto_now」オプションの挙動を詳しく調べてみた

$
0
0

Django モデルに登録日時や更新日時のフィールドを付加する場合、「auto_now_add」オプションや「auto_now」オプションを利用すると便利です。それらのオプションの挙動について詳しく調べてみたので、まとめておきます。

f:id:akiyoko:20200521233958p:plain

TL;DR


挙動

たとえば、

shop/models.py

from django.db import models


classBook(models.Model):
    """本モデル"""classMeta:
        db_table = 'book'
        verbose_name = verbose_name_plural = '本'

    title = models.CharField('タイトル', max_length=255)
    price = models.PositiveIntegerField('価格', null=True, blank=True)
    created_at = models.DateTimeField('登録日時', auto_now_add=True)
    updated_at = models.DateTimeField('更新日時', auto_now=True)

    def__str__(self):
        return self.title

というフィールドがあるとすると、

登録時

  • 「auto_now_add=True」のフィールド(created_at)に現在日時が自動的にセットされる
  • 「auto_now=True」のフィールド(updated_at)に現在日時が自動的にセットされる

更新時

  • 「auto_now=True」のフィールド(updated_at)に現在日時が自動的にセットされる

という挙動になります。


つまり、テストを書くとこういうことになります(参考までに freezegununittest.mockを使ったものを併記)。


shop/tests/test_models.py

from datetime import datetime
from unittest.mock import patch

from django.test import TestCase
from django.utils import timezone
from freezegun import freeze_time

from ..models import Book


classTestBook(TestCase):

    @freeze_time('2020-01-01 01:01:01')
    deftest_save_with_freezegun(self):
        book = Book(title='Django本', price=1500)
        # 登録
        book.save()

        # 登録日時・更新日時のどちらも値がセットされる
        self.assertEqual(book.created_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))
        self.assertEqual(book.updated_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))

        with(freeze_time('2020-02-02 02:02:02')):
            # 更新
            book.save()

        # 更新日時のみが更新される
        self.assertEqual(book.created_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))
        self.assertEqual(book.updated_at, datetime(2020, 2, 2, 2, 2, 2, tzinfo=timezone.utc))

    @patch('django.utils.timezone.now',
           return_value=datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))
    deftest_save_with_mock(self, _mock_now):
        book = Book(title='Django本', price=1500)
        # 登録
        book.save()

        # 登録日時・更新日時のどちらも値がセットされる
        self.assertEqual(book.created_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))
        self.assertEqual(book.updated_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))

        _mock_now.return_value = datetime(2020, 2, 2, 2, 2, 2, tzinfo=timezone.utc)
        # 更新
        book.save()

        # 更新日時のみが更新される
        self.assertEqual(book.created_at, datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc))
        self.assertEqual(book.updated_at, datetime(2020, 2, 2, 2, 2, 2, tzinfo=timezone.utc))



 
フィールドに現在日時が自動的にセットされる仕組みを見てみると、次のように、pre_save() で django.utils.timezone.now() が呼ばれています。

django.db.models.fields.DateTimeField.pre_save *1

defpre_save(self, model_instance, add):
        if self.auto_now or (self.auto_now_add and add):
            value = timezone.now()
            setattr(model_instance, self.attname, value)
            return value
        else:
            returnsuper().pre_save(model_instance, add)


そして django.utils.timezone.now() では、Django の設定ファイルの「USE_TZ」が True の場合は datetime.datetime.utcnow() が呼ばれています。

django.utils.timezone.now *2

defnow():
    """    Return an aware or naive datetime.datetime, depending on settings.USE_TZ."""if settings.USE_TZ:
        # timeit shows that datetime.now(tz=utc) is 24% slowerreturn datetime.utcnow().replace(tzinfo=utc)
    else:
        return datetime.now()


freezegun の freezegun.api.FakeDatetime が次のように datetime.datetime.now() や utcnow() などをモックしてくれているので、「auto_now_add」や「auto_now」にも適用できるのですね。よかった。

freezegun.api.FakeDatetime *3

classFakeDatetime(with_metaclass(FakeDatetimeMeta, real_datetime, FakeDate)):

    ...(略)...

    @classmethoddefnow(cls, tz=None):
        now = cls._time_to_freeze() or real_datetime.now()
        if tz:
            result = tz.fromutc(now.replace(tzinfo=tz)) + cls._tz_offset()
        else:
            result = now + cls._tz_offset()
        return datetime_to_fakedatetime(result)

    ...(略)...

    @classmethoddefutcnow(cls):
        result = cls._time_to_freeze() or real_datetime.utcnow()
        return datetime_to_fakedatetime(result)

    ...(略)...


 

「auto_now_add」や「auto_now」を使うことによる弊害

便利でよいのですが、二点ほど弊害があります。

1.任意の値で更新できない

実例を挙げると、

>>> from shop.models import Book
>>> from datetime import datetime
>>> from django.utils import timezone
>>> book = Book()
>>> book.updated_at = datetime(2020, 1, 1, 1, 1, 1, tzinfo=timezone.utc)
>>> book.save()
>>> book.updated_at
datetime.datetime(2020, 5, 21, 6, 41, 7, 219328, tzinfo=<UTC>)

という感じで、保存時に現在日時で上書きされてしまいます。

(参考)www.ianlewis.org


しかしながら、登録日時や更新日時フィールドに「auto_now_add」および「auto_now」オプションを利用する場合、任意の値で更新したいユースケースとしてはユニットテストのときくらいでしょうから、実害はあまり無いと言えるかもしれません。
 

2.管理サイトの詳細画面で表示されない

「auto_now_add」もしくは「auto_now」オプションを利用すると、自動的に editable オプションが False になるので、管理サイトの詳細画面で表示されなくなります。

f:id:akiyoko:20200521232712p:plain

django.db.models.fields.DateField.__init__ *4

classDateField(DateTimeCheckMixin, Field):
    ...(略)...

    def__init__(self, verbose_name=None, name=None, auto_now=False,
                 auto_now_add=False, **kwargs):
        self.auto_now, self.auto_now_add = auto_now, auto_now_add
        if auto_now or auto_now_add:
            kwargs['editable'] = False
            kwargs['blank'] = Truesuper().__init__(verbose_name, name, **kwargs)

    ...(略)...

classDateTimeField(DateField):
    ...(略)...

    # __init__ is inherited from DateField


詳細画面にフィールドを表示するだけであれば(任意の値で登録・更新できないが)、ModelAdmin の「fields」と「readonly_fields」に同時に列挙することで対応は可能です。

shop/admin.py

from django.contrib import admin

from .models import Book


classBookAdmin(admin.ModelAdmin):
    fields = ('title', 'price', 'created_at', 'updated_at')
    readonly_fields = ('created_at', 'updated_at')


admin.site.register(Book, BookAdmin)

f:id:akiyoko:20200521233140p:plain



これらの弊害については一応解決策がありますが、ちょっと面倒です。あまりオススメしません。

stackoverflow.com



 

宣伝

Django の本を3冊書きました。Django 開発のお供にどうぞ。

現場で使える Django の教科書《基礎編》

★ Amazon(電子版/ペーパー版)


★ BOOTH(ペーパー版)


現場で使える Django の教科書《実践編》

★ Amazon(電子版)


★ BOOTH(ペーパー版)


現場で使える Django REST Framework の教科書

★ Amazon(電子版)


★ BOOTH(ペーパー版)

Viewing all 52 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>