django-slackのカスタマイズ

django-slackはdjangoでslack通知するのに便利なモジュールです
ただ、カスタマイズ方法は分かりにくかったのでまとめました

公式ドキュメント
https://django-slack.readthedocs.io/

基本的な使い方は、こちらの方の記事がわかりやすいです
https://qiita.com/hfujima/items/d80b9dd059f7bcebf2a4

# 独自テンプレートを使いたい
まず、適当な場所に独自のテンプレートを作成します
```path/templates/slack/message.slack
{% extends django_slack %}

{% load django_slack %}

{% block text %}
# ここに独自のメッセージとかを入れる
{{ text }}
{% endblock %}
```
あとはそれをメッセージ送信時に指定するだけです
```python
import os
from django.conf import settings
from django_slack import slack_message

class Slack:
    @classmethod:
    def send(cls, message)
        slack_message(os.path.join(settings.BASE_DIR, 'path/templates/slack/message.slack'), {'text': message})
```
毎回指定するのはめんどくさいので、こんな感じでクラス化してしまった方が楽だと思います

# 送信するチャンネルを変更したい
`settings.py`に設定できる`SLACK_CHANNEL`は一つですが、通知するチャンネルはメッセージによって分けたいってことはあるかと思います
その場合も独自のテンプレートを使います
```path/templates/slack/message.slack
{% extends django_slack %}

{% load django_slack %}

{% block text %}
{{ text }}
{% endblock %}

{% block channel %}
# 送信したいチャンネル名
{{ channel }}
{% endblock %}
```
送信時にチャンネル名を渡します
```python
import os
from django.conf import settings
from django_slack import slack_message

class Slack:
    @classmethod:
    def send(cls, message)
        slack_message(os.path.join(settings.BASE_DIR, 'path/templates/slack/message.slack'), {'text': message, 'channel': '#othor_channel'})
```
同様に
`endpoin_url`、`icon_emoji`、`icon_url`、`token`ブロックでそれぞれ
`SLACK_ENDPOINT_URL`、`SLACK_ICON_EMOJI`、`SLACK_ICON_URL`、`SLACK_TOKEN`をメッセージごとに変えることができます

# ログ出力時のslack通知を独自テンプレートにする
基本的なログ出力時のslack通知については公式ドキュメントにもありますが
settings.pyの`LOGGING`に`django_slack.log.SlackExceptionHandler`のhandlerを追加して設定します
独自テンプレートを使う場合は`template`を追加してパスを指定します
```settings.py
import os

LOGGING = {
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
    },
    'handlers': {
        'slack_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django_slack.log.SlackExceptionHandler',
            # 独自テンプレートを設定
            'template': os.path.join(BASE_DIR, 'path/templates/slack/message.slack')
        },
    },
    'loggers': {
        'django': {
            'level': 'ERROR',
            'handlers': ['slack_admins'],
        },
    },
}
```
# ログ出力時のslack通知でエラーの場合のみ`@channel`を付ける
`LOGGING`のlevelをWARNINGにするとWARNINGとERRORの場合にslack通知されますが、ERRORの場合はすぐに気がつけるように`@channel`をつけたい場合
`SlackExceptionHandler`を継承して以下のようなテンプレートと独自クラスを作って設定します

```path/templates/slack/message.slack
{% extends django_slack %}

{% load django_slack %}

{% block text %}
# is_channel=Trueの場合は@channelをつける
{% if is_channel %}<!channel>{% endif %}
{{ text }}
{% endblock %}
```

```path/slack_exception_handler.py
import os
from django.conf import settings
from django_slack.log import SlackExceptionHandler as OriginalSlackExceptionHandler

class SlackExceptionHandler(OriginalSlackExceptionHandler):

    def __init__(self, **kwargs):
        super().__init__(template=os.path.join(settings.BASE_DIR, 'path/templates/slack/message.slack'))

    def send_message(self, *args, **kwargs):
        """
        Hook to update the message before sending.
        """
        # ERRORだった場合は@channelをつける
        is_channel = False
        subject = args[1].get('text')
        if subject.find('ERROR') == 0:
            is_channel = True
        args[1]['is_channel'] = is_channel

        return super().slack_message(*args, **kwargs)
```

```settings.py
import os

LOGGING = {
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse',
        },
    },
    'handlers': {
        'slack_admins': {
            'level': 'WARNING',
            'filters': ['require_debug_false'],
            'class': 'path.slack_exception_handler.SlackExceptionHandler',
        },
    },
    'loggers': {
        'django': {
            'level': 'WARNING',
            'handlers': ['slack_admins'],
        },
    },
}
```