【Django】template上で使用できる user について

# はじめに
　Djangoで、現在ログインしているユーザーの名前を画面上に表示させたい時はtemplate上で`{{ user.username }}`や`{{ user.get_username }}`とすることで実現できる。しかし、この`user`という変数はviews.pyで`render`関数を用いてtempletesに渡したり、`get_context_data()`をオーバーライドして変数を追加したりしていないのになぜ使えるのか。ここに疑問を持ったので少し調べてみた。

# 結論
　templateで使用できる変数はcontext（={<変数名>: <変数>, .....}）に格納されていて、このcontextは大きく以下の２種類の変数を含む。

1. views.pyでrender関数などを用いて渡された変数
2. settings.py内のTEMPLATESのOPTIONに指定されている'context_processers'で指定されるファイル内で定義された変数

　`user`は2.の説明にあたる変数であり、他にviews.pyで指定しなくても使える主な変数として`request`, `perm`, `message`などがある。

# どこに格納されているのか
　まずsetting.pyを見てみる。

```python:config/setting.py
#
# 省略
#

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

#
# 省略
#
```
setting.pyにあるTEMPLATES.OPTIONS.context_processorsで指定されているファイルは、以下の4つ。
`django.template.context_processors.debug`
`django.template.context_processors.request`
`django.contrib.auth.context_processors.auth`・・・・・・・`user`の在処
`django.contrib.messages.context_processors.messages`

### `user`の格納場所
```python:django.contrib.auth.context_processors
#
# 省略
#

def auth(request):
    """
    Return context variables required by apps that use Django's authentication
    system.

    If there is no 'user' attribute in the request, use AnonymousUser (from
    django.contrib.auth).
    """
    if hasattr(request, 'user'):
        user = request.user
    else:
        from django.contrib.auth.models import AnonymousUser
        user = AnonymousUser()

    return {
        'user': user,
        'perms': PermWrapper(user),
    }
```

`'user': user`を`return`することによって`user`がtemplate内で使えるようになる。`user.username`とし`user`内の`username`属性を取り出したり、AnonymousUserクラスをインスタンス化したあと、クラス内のget_userメソッドを使用し`user.get_username`とすることでログイン中のユーザー名が表示可能となる。

#### （参考）
　一番下にget_username関数がある。

```python:django.contrib.auth.models
class AnonymousUser:
    id = None
    pk = None
    username = ''
    is_staff = False
    is_active = False
    is_superuser = False
    _groups = EmptyManager(Group)
    _user_permissions = EmptyManager(Permission)

    def __str__(self):
        return 'AnonymousUser'

    def __eq__(self, other):
        return isinstance(other, self.__class__)

    def __hash__(self):
        return 1  # instances always return the same hash value

    def __int__(self):
        raise TypeError('Cannot cast AnonymousUser to int. Are you trying to use it in place of User?')

    def save(self):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def delete(self):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def set_password(self, raw_password):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    def check_password(self, raw_password):
        raise NotImplementedError("Django doesn't provide a DB representation for AnonymousUser.")

    @property
    def groups(self):
        return self._groups

    @property
    def user_permissions(self):
        return self._user_permissions

    def get_user_permissions(self, obj=None):
        return _user_get_permissions(self, obj, 'user')

    def get_group_permissions(self, obj=None):
        return set()

    def get_all_permissions(self, obj=None):
        return _user_get_permissions(self, obj, 'all')

    def has_perm(self, perm, obj=None):
        return _user_has_perm(self, perm, obj=obj)

    def has_perms(self, perm_list, obj=None):
        return all(self.has_perm(perm, obj) for perm in perm_list)

    def has_module_perms(self, module):
        return _user_has_module_perms(self, module)

    @property
    def is_anonymous(self):
        return True

    @property
    def is_authenticated(self):
        return False

    def get_username(self):
        return self.username
```