장고 초급)글 관리 권한 설정하기(request.user, permission)

하얀설표 | 작성시간 2024.06.29.

(2024.07.02. 수정됨.)

사용 환경 

OS : Windows 10
python : python 3.10.11
django : Djajgno 5.0.6

주요 파일 경로

blog
|- entry
|  |- views.py
|- templates
   |- index.html
   |- detail.html

눈치채셨겠지만, 현재 블로그에는 치명적인 문제가 있습니다.
"개인 블로그"임에도 글 작성과 수정, 삭제 작업을 아무나 수행할 수 있다는 것인데요.

이번에는 사이트 관리자만 이런 작업이 가능하도록 설정할 겁니다.

관리자만 작업을 수행할 수 있도록 하기

views.py

다음과 같이 글 관리 기능을 요청하는 이용자가 관리자가 맞는지 확인하는 check_permission 코드를 작성하고,
글 작성과 저장, 삭제 작업을 담당하는 post, edit, save, delete 함수 최상단에 check_permission 함수를 삽입해 각 코드가 작동할 때마다 제일 먼저 이용자를 확인하도록 해줍니다.

# entry/views.py
from django.contrib.auth.decorators import permission_required # 추가
from django.http.request import HttpRequest
...
@permission_required('is_admin', raise_exception=True) # 추가
def post(request: HttpRequest):
    ...
@csrf_protect
@permission_required('is_admin', raise_exception=True) # 추가
def save(request: HttpRequest, pk: int=None):
    ...
...
@permission_required('is_admin', raise_exception=True) # 추가
def edit(request: HttpRequest, pk: int):
    ...
@permission_required('is_admin', raise_exception=True) # 추가
def delete(request: HttpRequest, pk: int):
    ...

permission_required

permission_required는 장고에서 제공하는 데코레이터 중 하나입니다.
요청을 보낸 이용자가 해당하는 권한(permission)을 보유하고 있는지 확인합니다.

raise_exception의 값이 True이고 권한이 없다면 403 응답을, raise_exception의 갑이 True가 아니고 권한이 없다면 404 응답을 보냅니다.

로그인 여부 확인할 수 있도록 하기

권한이 잇는 이용자이지만, 로그인을 하지 않은 경우에는 로그인할 수 있는 경로를 제공해주어야 합니다.
index.html과 detail.html에서 로그인 상태를 확인할 수 있도록 다음과 같이 수정해줍니다.

# templates/index.html
<head></head>
<body>
    {% if request.user.is_anonymous %}
    <div>
        <a href="/admin/login/?next={{ request.get_full_path }}">로그인하기</a>
    </div>
    {% else %}
    <p>"{{ request.user.username }}"님</p>
    <form action="/admin/logout/?next={{ request.get_full_path }}" method="post">
        {% csrf_token %}
        <input type="submit" value="로그아웃">
    </form>
    {% endif %}
    <br>
    <h1>{{ title }}</h1>
    <a href="/entry/post/">글 작성하기</a>
    <article>
        {% for object in objects %}
        <p><a href="/entry/{{ object.pk }}">{{ object.title }}</a></p>
        {% empty %}
        <p>작성된 글이 없습니다.</p>
        {% endfor %}
    </article>
</body>

# templates/detail.html
<head></head>
<body>
    {% if request.user.is_anonymous %}
    <div>
        <a href="/admin/login/?next={{ request.get_full_path }}">로그인하기</a>
    </div>
    {% else %}
    <p>"{{ request.user.username }}"님</p>
    <form action="/admin/logout/?next={{ request.get_full_path }}" method="post">
        {% csrf_token %}
        <input type="submit" value="로그아웃">
    </form>
    {% endif %}
    <br>
    <h1>{{ object.title }}</h1>
    <a href="/entry/{{ object.pk }}/edit/">글 수정하기</a>
    <a href="/entry/{{ object.pk }}/delete/">글 삭제하기</a>
    <article>
        <div>
            {{ object.content|safe }}
        </div>
    </article>
</body>

request.user.is_anonymous

요청을 보낸 이용자가 로그인하지 않은 경우 True를 return하는 property입니다.

request.user.username

이용자의 닉네임은 username으로 보관되기 때문에 이를 호출하면 이용자 닉네임을 가져올 수 있습니다.

request.get_full_path

현재 방문하고 있는 페이지의 전체 url입니다.
로그인과 로그아웃은 작업 후에 url에 전달된 next parameter로 리다이렉트시키기 때문에 현재 페이지로 되돌아오기 위해 사용합니다.

로그인 상태 확인하기

이제 글 목록 페이지와 개별 글 페이지에서 로그인 상태를 확인할 수 있게 되었습니다.

로그인 상태 확인

로그아웃한 상태에서 글 작성 시도해보기

이제 로그아웃하거나 관리자가 아닌 이용자가 글을 관리하려고 시도하면 403 Fobidden error 페이지가 노출됩니다.

권한이 없는 경우



이 글의 댓글 기능은 일부러 막아놓았습니다. 궁금한 내용이 있다면 게시판을 이용해주세요!