Python の Web アプリケーションフレームワークである Django が、先週 (2021/12/07) に 4.0 へメジャーアップデートされました
同年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 %}
一度表示した後にリロードした結果が以下の画像で、キャッシュした値が使われていることを確認できますね。
注意
なお、現時点 (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})
レンダリングに使用するフォームとビューのテンプレートを以下のようにします。
<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>
<form action="/contact/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
これを画面に表示した結果が以下になります。
(例だから簡略化してるとは言え何ともつまらん画面だ...)
ContactForm.template_name
から指定したテンプレートのレンダリング結果が {{ form }}
に置き換わって、グリッドレイアウトによるフォームの表示が作成できるようになりました。
template_name
の他にも render()
から、直接↑の {{ form }}
に該当する文字列を生成できるようですが、とりあえず試すのは HTML ベースのカスタマイズだけにします。
正直これまでもフィールドを手動でレンダリングすることはできたので、テンプレートを個別に include
すれば同じことができたのですが、 Form インスタンスのみで再利用可能なフォームを作成できるのは良いですね。
(例だと汎用テンプレートを ContactForm
という固有のフォームに紐づけちゃってるけど気にしない)
まだ全然書き方を掴めてないですが、 Django の公式リポジトリに元となるテンプレートがあるので、ここら辺を参考にするのも良さそうです。
感想
今のところ、バージョン 3.0 に上がった時の ASGI support ほどの衝撃はなかった。