独自フィルターが必要になった理由
allauthのsocialaccountで、プロバイダ(twitter)から取得する画像の処理をviews.pyに書くのが面倒だったので独自フィルターを作りました。
twitterから取得できるprofile_image_url_httpsは、小さいサイズ(_normal)なので、独自フィルターを作成してこれを通常のサイズに変更していきます。
Django-allauthの仕様で書いてありますが、allauthが無くても基本は同じです。
twitterの画像の仕組み
twitter APIで取得できるURL
# デフォルト
profile_image_url_http = "https://pbs.twimg.com/profile_images/12341234/hoge_normal.png"
ファイル名の後ろに付く_normalが画像を小さくしてしまっているのでこれを加工する。
| 指定 | サイズ |
|---|---|
| _mini | 24 × 24 |
| _normal | 48 × 48 |
| _bigger | 73 × 73 |
| 無し | オリジナル |
もしviews.py内で処理したい場合は
# userのtwitter情報を取得
twitter_accunt = user.socialaccount_set.filter(provider='twitter')
# プロフ画像のURLを取得
t_image = twitter_accunt.values("extra_data")[0]["extra_data"]["profile_image_url_https"]
# _normalをreplaceで削除(置換)
t_image.replace("_normal", "")
これでオリジナルサイズの画像のURLが取得できる。
プロフ画像を取得するコードがちょっとナンセンスな気がしますが・・・w
もっとスマートにできる気も?
独自テンプレートフィルターを作る
前置きが長くなりましたが早速作ってみる。
-
アプリケーション直下に
templatetagsのディレクトリを作成 -
templatetags内に、空の__init__.pyファイルを作成 -
templatetags内に、hoge.pyファイルを作成
project dir
|- appname dir
|- templatetags
|- __init__.py
|- hoge.py
hoge.pyは{% load hoge %}と.htmlで呼び出す名前になります。
ここまで出来たらhoge.pyファイルにフィルターの中身を書いていく。
今回は画像のURLの_normalを削除したいので、そのフィルターを作る。
# この2つはコピペでOK
from django import template
register = template.Library()
# twitter_replaceというフィルターを登録
@register.filter
def twitter_replace(value):
# replaceで書き換える
return value.replace("_normal","")
これでtwitter_replaceをテンプレートフィルターとして使えば、置換されるようになります。
テンプレートに反映させる
<!-- allauthのsocialaccount用 -->
{% load socialaccount %}
<!-- 先程作ったファイルを読み込む -->
{% load hoge %}
<!-- userはviews.pyの変数 -->
{% get_social_accounts user as accounts %}
<img src="{{ accounts.twitter.0.extra_data.profile_image_url_https | twitter_replace }}">
これでオリジナルサイズの画像が表示できるようになります
表示するページが1ページならviews.pyに書いても良いかと思いますが、複数ページに表示したりfor文で回す時などフィルターを作った方が使い回せるので便利だと感じました。
今回の記事とは関係ありませんが、いい感じに{% include %}で呼び出すのもありなのかな?
補足
-
INSTALLED_APPSにあるアプリにしか独自テンプレートフィルターは作れない。 - 独自テンプレートフィルターを作成した後は、仮想サーバーを再起動しないと反映されない。