1. taki_21

    Posted

    taki_21
Changes in title
+【Django】template上で使える`user`について
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,148 @@
+# はじめに
+ Djangoで、現在ログインしているユーザーの名前を画面上に表示させたい時はtemplate上で`{{ user.username }}`や`{{ user.get_username }}`とすることで実現できる。しかし、この`user`という変数はviews.pyで`render`関数を用いてtempletesに渡したり、`get_text_data()`をオーバーライドして変数を追加したりしていないのになぜ使えるのか。ここに疑問を持ったので少し調べてみた。
+
+# 結論
+ templateで使用できる変数はcontext(={<変数名>: <変数>, .....})に格納されていて、このcontextは大きく以下の2種類の変数を含む。
+
+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
+```