AI웹 개발자 과정 공부 (팀스파르타)/Django (장고)

24.04.22_TIL (2) (Django Authentication System)

티아(tia) 2024. 4. 22. 21:02
728x90

 

++ 장고 공식 문서는 항상 확인하기 

https://docs.djangoproject.com/en/4.2/

 

 

 

1.  로그인 구현하기 

 

  • accounts 앱 새로 만들기
python manage.py startapp accounts
  • settings.py 에 'accounts' 추가하기
  • my_first_pjt 에 urls.py 에 path 추가하기
path('accounts/', include('accounts.urls')),

 

  •  accounts 의 urls.py 파일을 생성한다.
from django.urls import path
from . import views

app_name = 'accounts'
urlpatterns = []

 

 

 

 

 

  •  accounts 의 urls.py 파일 수정
from django.urls import path
from . import views

app_name = "accounts"
urlpatterns = [
    path("login/", views.login, name="login"),
]

 

  • accounts 의 views.py 작성
from django.shortcuts import render
from django.contrib.auth.forms import AuthenticationForm


def login(request):
    form = AuthenticationForm()
    context = {"form": form}
    return render(request, "accounts/login.html", context)

 

  • accounts에 templates 파일을 만들고 그 안에 accounts를 또 만들어서 경로 설정!
  • login.html 파일을 만들어준다.
{% extends "base.html" %}

{% block content %}
    <h1>로그인</h1>

    <form action="{% url 'accounts:login' %}" method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">로그인</button>
    </form>

{% endblock content %}

 

 

 

 

 

 

 

 

 

 

 

 

2.  로그인을 해보자.

  • Django 는 User / Staff / Superuser 로 구분
  • Superuser를 만들어보자.
python manage.py createsuperuser # 슈퍼유저 생성
  • username : admin
  • password : admin1234

 

 

  • accounts 의 views.py 를 수정하자.
def login(request):
    if request.method == "POST":
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            auth_login(request, form.get_user())
            return redirect("index ")
    else:
        form = AuthenticationForm()
    context = {"form": form}
    return render(request, "accounts/login.html", context)

 

 

  • base.html 을 수정해서 로그인 버튼을 어딜가도 볼 수 있게 만들자.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="navbar">
      <a href="{% url 'accounts:login'%}">로그인</a>
    </div>

    <div class="container">
      {% block content %}
      {% endblock content %}
    </div>
  </body>
</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

3.  로그아웃 구현하기.

 

  •  accounts 의 urls.py 파일 수정
path("logout/", views.logout, name="logout"),

 

  • accounts 의 views.py 작성
from django.shortcuts import render, redirect
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout


def login(request):
    if request.method == "POST":
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            auth_login(request, form.get_user())
            return redirect("index")
    else:
        form = AuthenticationForm()
    context = {"form": form}
    return render(request, "accounts/login.html", context)

def logout(request):
    auth_logout(request)
    return redirect("index")

 

  • base.html 을 수정해서 로그아웃 버튼을 만들자.
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div class="navbar">
      <a href="{% url 'accounts:login'%}">로그인</a>
      <form action="{% url 'accounts:logout' %}" method='POST'>
        {% csrf_token %}
        <input type="submit" value="로그아웃"></input>
      </form>
    </div>

    <div class="container">
      {% block content %}
      {% endblock content %}
    </div>
  </body>
</html>

 

 

 

 

  • accounts 의 views.py 수정
def logout(request):
    if request.method == "POST":
        auth_logout(request)
    return redirect("index")

 

 

 

 

 

 

 

 

 

 

4.  상태코드 수정해주기

 

  • http://127.0.0.1:8000/articles/9999 번째 글을 가려고 하면 펑!하고 터짐. 왜냐면 9999번째 글은 없으니까
  • articles 의 views.py 에서 수정을 해주어야 한다.- detail 에서 수정해줌 / update와 delete 도 같이 수정해준다.
  • 사용자가 없는 파일을 찾았으니까 404에러를 보일 수 있도록 한다.
from django.shortcuts import render, redirect, get_object_or_404

...

article = get_object_or_404(Article, pk=pk)

 

 

 

 

 

 

  • View Decorators 해준다. 포스트가 아닌 요청은 다 튕겨내버린다.
  • accounts 의 views.py 에서 수정을 해주어야 한다 - logout 바꾸어줌
from django.views.decorators.http import require_POST

....

@require_POST
def logout(request):
  auth_logout(request)
  return redirect("index")

 

  • login 쪽에도 수정해주어야함 
from django.views.decorators.http import require_POST, require_http_methods

@require_http_methods(["GET", "POST"])
def login(request):

 

 

 

 

 

 

 

 

 

 

5.  Template with Auth 로그인과 로그아웃하면 화면 다르게 보이기

  • request.user 도 그 중에 하나로 템플릿을 랜더링할때 현재 로그인한 사용자를 나타내는 auth.User클래스의 인스턴스 또는 AnoymousUser 인스턴스를 request.user 로 접근할 수 있습니다.
  • base.html 을 수정해본다.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <div class="navbar">
        {% if request.user.is_authenticated %}
            <h3>안녕하세요, {{ user }}님</h3>
            <form action="{% url 'accounts:logout' %}" method="POST">
                {% csrf_token %}
                <input type="submit" value="로그아웃">
            </form>
        {% else %}
            <a href="{% url 'accounts:login'%}">로그인</a>
        {% endif %}
    </div>

    <div class="container">
        {% block content %}
        {% endblock content %}
    </div>

</body>
</html>

 

 

  •  로그인 했을 때만 글 작성을 보여주기 위해서 바꾸어준다.
  • acoounts 의 views.py 에 가서 수정한다.
@require_POST
def logout(request):
  if request.user.is_authenticated:
    auth_logout(request)
  return redirect("index")

 

  • articles 의 articles.html 로 가서 수정해준다. 
{% extends 'base.html' %} 

{% block content %}
  <h1> articles </h1>

  {% if request.user.is_authenticated %}
    <a href="{% url 'articles:create' %}">
      <button> 새로운 글 작성</button>
    </a>
  {% else %}
    <a href="{% url 'accounts:login' %}"> 로그인하고 글 작성하기 </a>
  {% endif %}
  
  <ul>
    {% for article in articles %}
      <li>
        <a href="{% url 'articles:detail' article.pk %}">
        <p>글 번호 : {{ article.id }}</p>
        <p>글 제목 : {{ article.title }}</p>
        </a>
        <hr>
      </li>
    {% endfor %}
  </ul>

{% endblock content %}

 

 

 

  • http://127.0.0.1:8000/articles/create/ 이렇게 적었을 때도 가버리면 안되서 막아준다. post로 접근 했을 때에만 갈 수 있게! 아래 코드를 작성하면 바로 get 방식으로 접근해도 로그인 페이지로 이동하는 것을 볼 수 있다.
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_http_methods

....

@login_required
def create(~~

 

 

 

 

 

 

  • http://127.0.0.1:8000/articles/create/ 으로 접근하고 나서 로그인을 하고 나면 바로 글 작성할 수 있게 로직을 짜보자.
  • accounts의 views.py 에서 수정해준다.
@require_http_methods(["GET", "POST"])
def login(request):
    if request.method == "POST":
        form = AuthenticationForm(data=request.POST)
        if form.is_valid():
            auth_login(request, form.get_user())
            next_url = request.GET.get("next") or "index"
            return redirect(next_url)
    else:
        form = AuthenticationForm()
    context = {"form": form}
    return render(request, "accounts/login.html", context)

 

  • accounts의 login.html 을 수정해준다.
{% extends "base.html" %}

{% block content %}
    <h1>로그인</h1>

    <form action="" method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">로그인</button>
    </form>

{% endblock content %}

 

 

 

 

 

  • articles 의 views.py 에서 수정 - 로그인 하지 않은 사람이 삭제하지 않도록 하기.
@require_POST
def delete(request, pk):
  if request.user.is_authenticated:
    article = get_object_or_404(Article, pk=pk)
    article.delete()
  return redirect("articles:articles")

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형