Help us understand the problem. What is going on with this article?

Django 1.11 LTS 主な変更点まとめ

More than 1 year has passed since last update.

2017年4月4日、Django 1.11 LTSがリリースされました!
今回のバージョンはLTS(Long Term Support=長期サポート)なので、非LTSバージョンよりサポート期間が長めになっています。サポート期間についての詳細は以下URL「Supported Versions」を確認してください。
https://www.djangoproject.com/download/

それでは、release notesに載っている主な変更点について解説します。

Python2サポートは1.11で最後

1.11はPython2をサポートする最後のバージョンです。次の2.0からはPython3のみサポートになります。
1.11のサポート期限は2020年4月までなので、それまでにはPython3への移行を終える必要があります。1

Deprecating warningsがデフォルトで無効に

Deprecating warningsがデフォルトで無効になりました。Python自体のデフォルトの挙動に合わせたとのことです。
これによって、1.11と1.8両方をサポートするサードパーティアプリケーションを開発する際、警告メッセージを回避するコードを書く必要がなくなりました。
今公開しているサードパーティアプリケーションのサポート対象に次回リリースされる2.0を含める場合、以下がDjango推奨の移行手順です。

  1. バージョン1.11より前のバージョンのサポートを切る。
  2. テストはpython -Wdで実行するようにして、Deprecating warningsが出るようにする。
  3. Deprecating warningsが出ていたら、出ないように修正する。

主な新機能

What’s new in Django 1.11の最初の3機能+その他の個人的に気になる機能について解説します。(それ以外の細かいのは数が多いので省略)

Class-based model indexes

モデルのインデックス指定は今までField.db_index、またはMeta.index_togetherを使っていましたが、1.11からはMeta.indexesにインデックスを表すクラスで指定できるようになりました。
以下が使用例です。

models.py
from django.db import models


class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    price = models.IntegerField()

    class Meta:
        indexes = [
            models.Index(fields=['title', 'author']),
            models.Index(fields=['price'], name='price_idx'),  # インデックスに名前を付けられる
        ]

これによって、B-tree以外のインデックスを指定することが可能になりました。例えば、GinIndexクラスを使うことで、PostgreSQL
の独自機能であるGinインデックスを指定することができます。

Template-based widget rendering

オリジナルのWidgetクラスを作成する際、HTML部分をテンプレートに分けることができるようになりました。
どれだけ便利になったか確認するため、1.8のWidgetクラスはどう書いていたか見てみましょう。

widgets_1_8.py
from django import forms
from django.forms.utils import flatatt
from django.utils.encoding import force_text
from django.utils.html import format_html


class RangeWidget(forms.Widget):
    def render(self, name, value, attrs=None):
        final_attrs = self.build_attrs(attrs, name=name)
        if value is None:
            value = ''
        if value != '':
            final_attrs['value'] = force_text(value)
        return format_html('<input type="range"{}>',
                           flatatt(final_attrs))

今まではHTML部分もrenderメソッドの中に書く必要があり、ちょっと読みにくいです。もっと複雑な仕様になるとスパゲッティコードになる可能性もあります。
次に、1.11での書き方を見てみましょう。

widgets.py
from django import forms


class RangeWidget(forms.Widget):
    template_name = 'forms/widgets/range.html'
range.html
<input type="range" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}{% if widget.value %} value="{{ widget.value }}"{% endif %}>

HTML部分が別ファイルに分かれたので、コードの見通しがかなり良くなりました。テンプレートの書き方はDjangoのソースコードのforms/templates/django/forms/widgets/以下にあるhtmlファイルを見れば参考になります。

Subquery expressions

モデル操作時にサブクエリを使うことができるようになりました。
stackoverflowで「django subquery」 で検索すると結構前から需要がある機能のようですが、ようやく実装されました。
Pythonコードの何がどういうクエリになるか検証するために、ドキュメントのサンプルと同じモデルを作って、以下のような図を作ってみました。
検証にはdjango-debug-toolbardebugsqlshellコマンドを使っています。データベースは公式ドキュメントと違ってSQLiteを使っていますが、投げられるクエリはだいたい同じです。

Subqueryの使用例

公式ドキュメント: https://docs.djangoproject.com/en/1.11/ref/models/expressions/#subquery-expressions
Pythonコード:
Subquery-python.jpg
クエリ:
Subquery-sql.jpg

Existsの使用例

公式ドキュメント: https://docs.djangoproject.com/en/1.11/ref/models/expressions/#exists-subqueries
Pythonコード:
Exists-python.jpg
クエリ:
Exists-sql.jpg

その他

個人的に気になる新機能

The Jinja2 template backend now supports context processors by setting the 'context_processors' option in OPTIONS.」(テンプレートバックエンドがJinja2でもcontext_processorsが使えるようになった)が気になっています。以前、1.8で検証した時には使えなかったのですが、これで気軽にJinja2を採用できそうです。


  1. もっとも、Python2.7のサポート期限は2020年までなので、Djangoでのサポートとは関係なく、そろそろPython3移行を検討するべきです。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away