4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

某 f 社のアドベントカレンダーAdvent Calendar 2021

Day 16

Django 4.0 がリリースされたので新機能を試してみた

Last updated at Posted at 2021-12-15

Python の Web アプリケーションフレームワークである Django が、先週 (2021/12/07) に 4.0 へメジャーアップデートされました :tada: :tada: :tada:
同年4月に LTS 版である Django 3.2 がリリースされたので業務で使う予定は全然ないんですが、プライベートで試してみた新機能について書いていこうと思います。
余裕ができたら他の機能についてもぼちぼち追加していこうかなー (やるとは言ってない)。

Redis cache backend

キャッシュに Redis を指定できるようになりました。
これまでも django-redis を入れると使えましたが、やはり公式でサポートされていると安心感が違いますね。
導入方法は簡単で公式ドキュメントに書いてあるように、以下のようなコードを settings.py に追加して redis-py をインストールするだけです。
(一緒に hiredis-py もインストールしておくのが推奨らしいです)

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.redis.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379',
    }
}

試しに以下のテンプレートのように、サーバサイドで生成した現在時刻の表示部に適用してみましょう。

{% load cache %}

<p>Without cache:</p>
<span>{{ now }}</span>

{% cache 5 timer %}
<p>With cache:</p>
<span>{{ now }}</span>
{% endcache %}

一度表示した後にリロードした結果が以下の画像で、キャッシュした値が使われていることを確認できますね。

django-redis-cache.png

注意

なお、現時点 (2021/12/16) では、以下のように bool 値を保存するとクラッシュするバグがあるので注意してください。
こちらは 2022/01/04 に修正リリースが入る予定のようです。

>>> from django.core.cache import cache
>>> cache.set('foo', True)
...
redis.exceptions.DataError: Invalid input of type: 'bool'. Convert to a bytes, string, int or float first.

Template based form rendering

これまで Django の Form クラスに固定で紐づけられていたテンプレートをカスタマイズできる機能です。

言葉だけだと何のこっちゃかわかりにくいので、試しにフォーム要素をグリッドレイアウトで並べるテンプレートを作ってみました。
フィールドとかは公式ドキュメントにある ContactForm を参考にしています。

まず、以下の ContactForm.template_name に作成したテンプレートへのパスを指定します。
テンプレートのパスは INSTALLED_APPS に登録したアプリフォルダの templates/ 下から見た位置になります。

from django import forms
from django.http import HttpResponseRedirect
from django.shortcuts import render


class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    message = forms.CharField(widget=forms.Textarea)
    sender = forms.EmailField()
    cc_myself = forms.BooleanField(required=False)

    template_name = 'grid.html'


def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            return HttpResponseRedirect(reverse('/thanks/'))
    else:
        form = ContactForm()

    return render(request, 'contact.html', {'form': form})

レンダリングに使用するフォームとビューのテンプレートを以下のようにします。

grid.html
<div style="display: grid; grid-template-columns: 200px 200px; gap: 10px;">
  {% for field, errors in fields %}
  <div style="grid-row: {{ forloop.counter }}; grid-column: 1;">{{ field.label_tag }}</div>
  <div style="grid-row: {{ forloop.counter }}; grid-column: 2;">{{ field }}</div>
  {% endfor %}
</div>
contact.html
<form action="/contact/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit">
</form>

これを画面に表示した結果が以下になります。
(例だから簡略化してるとは言え何ともつまらん画面だ...)

django-form-template.png

ContactForm.template_name から指定したテンプレートのレンダリング結果が {{ form }} に置き換わって、グリッドレイアウトによるフォームの表示が作成できるようになりました。
template_name の他にも render() から、直接↑の {{ form }} に該当する文字列を生成できるようですが、とりあえず試すのは HTML ベースのカスタマイズだけにします。

正直これまでもフィールドを手動でレンダリングすることはできたので、テンプレートを個別に include すれば同じことができたのですが、 Form インスタンスのみで再利用可能なフォームを作成できるのは良いですね。
(例だと汎用テンプレートを ContactForm という固有のフォームに紐づけちゃってるけど気にしない)

まだ全然書き方を掴めてないですが、 Django の公式リポジトリに元となるテンプレートがあるので、ここら辺を参考にするのも良さそうです。

感想

今のところ、バージョン 3.0 に上がった時の ASGI support ほどの衝撃はなかった。

4
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?