Django のおすすめライブラリ


Friday I/O ですー。
[株式会社ワムウ](http://wamw.jp)では、毎週金曜日は `興味がある事柄に取り組み、その成果を何らかの形でアウトプットする日` としております。
みんな金曜日は好きな事やったらいいよ！

## はじめに

Golangやらなんやらと色々便利な言語がある昨今ではありますが、さっくりWebアプリを作るのであればやっぱり最強（だと個人的には思ってる）なPythonの `Django` ちゃんであります。
今回はDjangoでWebアプリを作る際にいつも使うライブラリをまとめてみました。


## django-cacheops

https://github.com/Suor/django-cacheops

ORM経由でのDBアクセスを勝手にキャッシュしてくれるライブラリです。
入れてちょこっと設定するだけでよしなにしてくれるので大変便利で御座います。
その他、 `Function Cache` と `View Cache` の仕組みもあるので、キャッシュ戦略はとりあえずこれ使っとけば良い感ある。


## django-choices

https://github.com/bigjason/django-choices

ModelやFormのChoicesを綺麗に書けるようになるライブラリ。

```python
# 普通の Choices の書き方
class Person(models.Model):
    # Choices
    PERSON_TYPE = (
        ("C", "Customer"),
        ("E", "Employee"),
        ("G", "Groundhog"),
    )

    # Fields
    name = models.CharField(max_length=32)
    type = models.CharField(max_length=1, choices=PERSON_TYPE)
```

```python
# django-choices を使った場合
from djchoices import DjangoChoices, ChoiceItem

class Person(models.Model):
    # Choices
    class PersonType(DjangoChoices):
        customer = ChoiceItem("C")
        employee = ChoiceItem("E")
        groundhog = ChoiceItem("G")

    # Fields
    name = models.CharField(max_length=32)
    type = models.CharField(max_length=1, choices=PersonType.choices)
```

定数としても利用できるので便利。

```python
person = Person.objects.get(1)
if person.type == Person.PersonType.customer:
    pass
```


## django-debug-toolbar

https://github.com/jazzband/django-debug-toolbar

言わずもがなですけども、デバッグ用の便利機能を画面に表示してくれるやつ。
これないともう仕事出来ないレベル。
脳死で入れといておk。

![Image](https://camo.githubusercontent.com/577d78f4c1fdb33761f2c8e541909c117a67f8ee/68747470733a2f2f7261772e6769746875622e636f6d2f6a617a7a62616e642f646a616e676f2d64656275672d746f6f6c6261722f6d61737465722f6578616d706c652f646a616e676f2d64656275672d746f6f6c6261722e706e67)


## django-extensions

https://github.com/django-extensions/django-extensions/

お名前の通り django を色々と拡張してくれるライブラリ。
[manage.py に色々と便利コマンドを追加](https://django-extensions.readthedocs.io/en/latest/command_extensions.html)してくれたり、[管理画面にオートコンプリートの機能を追加](https://django-extensions.readthedocs.io/en/latest/admin_extensions.html)したり、[お便利モデルフィールド群を用意](https://django-extensions.readthedocs.io/en/latest/field_extensions.html)してくれたり盛り沢山です。

URL一覧を表示する以下のコマンドが地味に便利。

```console
./manage.py show_urls
```

また、[runserver_plus](https://django-extensions.readthedocs.io/en/latest/runserver_plus.html)という機能があるのですが、これを使うとブラウザに表示されるエラー画面でデバッグが出来る様になります！
`runserver_plus` を利用するには[Werkzeug](http://werkzeug.pocoo.org/)というライブラリが必要です。

```console
./manage.py runserver_plus 0.0.0.0:8000
```

![runserver-plus.png](https://qiita-image-store.s3.amazonaws.com/0/12537/ef255171-acbc-f3f2-322b-e0b6ab312b60.png "runserver-plus.png")


## django-import-export

https://github.com/django-import-export/django-import-export

`CSVファイル等` を管理画面からインポートしたりエクスポートしたり出来るライブラリ。
おじさん達すぐ `CSVファイルちょうだい！` っていうから、これ入れとくと便利。
[tablib](https://github.com/kennethreitz/tablib)がサポートするフォーマット（ExcelとかJSON）を取り扱えますよ。

![Image](https://raw.githubusercontent.com/django-import-export/django-import-export/master/docs/_static/images/django-import-export-change.png)

デフォルトで使うと無駄に処理が多くて重くなるので、手前味噌ですが以下の記事を参考にすると良いと思います。

[django-import-exportのインポートがくそ遅い理由と対処](http://qiita.com/odoku/items/d3728c86248f7cc68635)


## django-polymorphic

https://github.com/django-polymorphic/django-polymorphic

[Djangoのマルチテーブル継承](https://docs.djangoproject.com/en/1.11/topics/db/models/#multi-table-inheritance)を利用する際には是非入れといた方が良いライブラリ。
モデルインスタンスのダウンキャストを勝手にやってくれます。

```python
from polymorphic.models import PolymorphicModel

class Animal(PolymorphicModel):
    name = models.CharField('name', max_length=50)

class Dog(Animal):
    def say(self):
        return '{}: わんわん'.format(self.name)

class Cat(Animal):
    def say(self):
        return '{}: にゃーん'.format(self.name)

Dog.objects.create(name='ポチ')
Cat.objects.create(name='タマ')

for animal in Animal.objects.all():
    print(animal.say())  # 犬なら「わんわん」で猫なら「にゃーん」
```


## django-security

https://github.com/sdelements/django-security/

セキュリティ対策用のミドルウェアがいっぱい入ってるライブラリ。
自分で書いてもいいけど、既にあるなら使った方が楽ですよね。


## django-storages

https://github.com/jschneier/django-storages

アップロードファイルを `S3` とかで管理したいなーって時に利用すると便利なライブラリです。
Webアプリが冗長構成を取る場合なんかは必須。


## django-widget-tweaks

https://github.com/jazzband/django-widget-tweaks

DjangoのFormをレンダリングする際に `classを追加したい` 時とかってあると思うんですけど、そういう場合って結構面倒なんですよね。
`django-widget-tweaks` を使うと簡潔に書けるので、絶対に使った方が良いです。

Django標準ではこんな書き方ですが。。。

```python
# forms.py
class LoginForm(forms.Form):
    username = forms.CharField(
        'ユーザー名',
        max_length=100,
        widget=forms.TextInput(attrs={'class': 'input-username'})
    )
    password = forms.CharField(
        'パスワード',
        max_length=100,
        widget=forms.PasswordInput(attrs={'class': 'input-password'})
    )

---

<!-- login.html -->
<form>
    {{ form.username }}
    {{ form.passowrd }}
    <button type="submit">Login</button>
</form>
```

`django-widget-tweaks` を使うとこうなります。

```python
# forms.py
class LoginForm(forms.Form):
    username = forms.CharField('ユーザー名', max_length=100)
    password = forms.CharField('パスワード', max_length=100)

---

<!-- login.html -->
{% load widget_tweaks %}
<form>
    {% render_field form.username class="input-username" %}
    {% render_field form.passowrd class="input-password" type="password" %}
    <button type="submit">Login</button>
</form>
```

HTMLを書く雰囲気で書けるので素敵。


## django-betterforms

https://github.com/fusionbox/django-betterforms

かゆいところに手が届いてるFormを作成できるライブラリですよ。
複数のFormを1つのFormとして利用出来る [MultiForm](https://django-betterforms.readthedocs.io/en/latest/multiform.html) ってのが特に便利です。

```python
class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('username', 'password')


class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('first_name', 'last_name')


class UserProfileMultiForm(MultiModelForm):
    form_classes = {
        'user': UserForm,
        'profile': ProfileForm,
    }

class UserSignupView(CreateView):
    form_class = UserProfileMultiForm
    success_url = reverse_lazy('home')

    def form_valid(self, form):
        user = form['user'].save()
        profile = form['profile'].save(commit=False)
        profile.user = user
        profile.save()
        return redirect(self.get_success_url())
```


## djangorestframework

Djangoを使って `Rest API サーバー` を作りたいーって時に利用すると大変便利なライブラリです。
ライブラリってか別のフレームワークになる感は否めないぐらい巨大なライブラリです。
巨大ゆえ説明が面倒なので偉大な先人のエントリーを参照されたし。

[Django REST Frameworkを使って爆速でAPIを実装する](http://qiita.com/kimihiro_n/items/86e0a9e619720e57ecd8)


## FactoryBoy

https://github.com/FactoryBoy/factory_boy

テストに必要なモデルデータ作る時とかに大変重宝致します！
リレーション関係にあるデータも一緒に作れるので、テスト書くときにダラダラとデータの準備をする必要がなくなります。

```python
class ProfileFactory(DjangoModelFactory):
    user = factory.SubFactory('app.users.factories.UserFactory')
    name = Faker('name')
    name_kana = Faker('kana_name')

    class Meta:
        model = Profile
        django_get_or_create = ('user',)


class UserFactory(DjangoModelFactory):
    email = Faker('email')
    password = factory.PostGenerationMethodCall('set_password', 'hogehoge')
    profile = factory.RelatedFactory(ProfileFactory, 'user')

    class Meta:
        model = User
        django_get_or_create = ('email',)


user = UserFactory()
assert user.profile.name is not None
```


## dateutil

https://github.com/dateutil/dateutil/

DjangoってかPythonのライブラリなんですけど、便利なので書いときますね。
名前のとおり、 `日時の操作に関するユーティリティ` を提供してくれるライブラリです。
[timedelta](https://docs.python.jp/3/library/datetime.html#timedelta-objects) の強化版である [relativedelta](https://dateutil.readthedocs.io/en/stable/relativedelta.html) がとにかく便利。
`timedelta` は `n日` までしか指定できないのですけど、 `relativedelta` だと `nヵ月` とか指定出来るのです。

```python
assert datetime(2000, 1, 1) + relativedelta(months=1) == datetime(2000, 2, 1)
datetime(2000, 1, 31) + relativedelta(months=1) == datetime(2000, 2, 29)
```

あと、 標準的な日時フォーマットであれば自動でパースしてくれる [parser](https://dateutil.readthedocs.io/en/stable/parser.html) も便利ですよ。

```
assert parse('2000-10-15') == datetime(2000, 10, 15)
```


## Raven (Sentry)

https://docs.sentry.io/clients/python/integrations/django/

ライブラリってか `エラートラッキングサービスのクライアント` なんですけども、非常に便利なので紹介しておきます。
Webアプリ上で投げられた例外等を検知して、メールやSlackへ通知を送ってくれます。
本番環境でエラーが起きた際に通知が来るようにしておくと、 `おじさん達に怒られる前にこっそり直す` という事が出来ます。
エラーの内容も `Sentryの管理画面上で確認できる` ので、わざわざログファイルをあさったりもしなくて済みます。
バグの対応速度が段違いに向上するので、是非利用してみてください。


## まとめ

他にも沢山のライブラリがDjangoにはあるので、色々探してみると楽しいと思います。
[Awesome Django](https://github.com/rosarior/awesome-django)で大量にライブラリが紹介されてるので、眺めてみるのも良いと思います。

`便利なライブラリあったよー` とか `ないから作ったよー` とか教えてくれるとおじさん嬉しいなー。