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")
반응형