akiyoko blog

akiyoko の IT技術系ブログです

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

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

補講その1として今回は、「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.7 3.4 3.5 3.6 3.7
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 を参考