일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- programmers
- Django
- python
- 그리디
- java
- 리그오브레전드
- 백준
- 롤
- 코딩테스트
- SQL
- 자바
- 알고리즘
- 내일배움캠프
- 라이엇
- Riot
- github
- lol
- 탐욕알고리즘
- greedy
- 프로그래머스
- API
- 코딩테스트준비
- drf
- 파이썬
- 장고
- 스파르타내일배움캠프
- sort
- git
- 그리디알고리즘
- 스파르타내일배움캠프TIL
- Today
- Total
Lina's Toolbox
Django로 회원가입 기능 구현하기 본문
Django의 Auth System을 이용해서 기본적인 회원기능을 구현 해보자!
회원가입
- Django는 기본 auth.User를 가지고 있기에 이를 기반으로한 기본적인 회원가입 ModelForm을 제공하고 있습니다.
- UserCreationForm
- Django는 OpenSource이다
- 장고 공식 깃허브 참조하기!! (https://github.com/django/django/blob/944745afe2ec45aed30cef799c250107f1364ca7/django/contrib/auth/forms.py#L196)
- username과 password 로 새로운 user를 생성하는 ModelForm
- username, password1, password2를 가짐
구현하기
(signup) accounts/forms.py
from django import forms
class ArticleForm(forms.Form):
title = forms.CharField(max_length=10)
content = forms.CharField()
(signup) accounts/views.py
from django.contrib.auth.forms import UserCreationForm
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect("index")
else:
form = UserCreationForm()
context = {"form": form}
return render(request, "accounts/signup.html", context)
post일경우는 바인딩 폼 만든다. (request.POST) 채워줌
(signup) accounts/templates/accounts/signup.html
{% extends "base.html" %}
{% block content %}
<h1>회원가입</h1>
<form action="{% url "accounts:signup" %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">회원가입</button>
</form>
{% endblock %}
(signup) base.html
<a href="{% url 'accounts:signup'%}">회원가입</a>
가입 및 편의성 업데이트
- 가입하고 바로 로그인까지 되면 좋을 것 같아요!
- 로그인? → 세션 생성해주기 → django가 해주던데 → login()
(session) accounts/views.py
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
auth_login(request, user)
return redirect("index")
else:
form = UserCreationForm()
context = {"form": form}
return render(request, "accounts/signup.html", context)
request.user
→ 장고가 알아서, request객체 안의 쿠키에서 sid 빼서, 세션 테이블에서 비교해서, 우리 실제 user테이블에 있는 user 객체를 할당해줌
매우편함!
회원탈퇴
💡 게시글을 지우는 것과 크게 다를 것이 없습니다. 마치 게시글을 지우듯이 DB에서 User를 지워주면 됩니다!
구현하기
1. accounts/urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
path("login/", views.login, name="login"),
path("logout/", views.logout, name="logout"),
path("signup/", views.signup, name="signup"),
path("delete/", views.delete, name="delete"),
]
2. accounts/views.py
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
return redirect("index")
- 그런데 회원탈퇴했는데도 쿠키에 세션 아이디와, 세션 테이블에 아직 남아있다?
- 만약 탈퇴하면서 해당 유저의 세션도 지우고 싶다면?
- → logout()을 사용하면 되겠죠?
@require_POST
def delete(request):
if request.user.is_authenticated:
request.user.delete()
auth_logout(request)
return redirect("index")
탈퇴하고 → 세션지우고. 이 순서가 바뀌면 안됩니다!
- 어차피 회원 탈퇴 후 남아있는 저 세션 아이디로 받은 값은, 어차피 저걸로 유저를 찾아도 해당 유저가 없기 때문에 의미는 없다.
- 그래도..깔끔하게 세션까지 삭제하자!
- → auth_logout
3. base.html 에 회원 탈퇴버튼 추가
(delete) base.html
<form action="{% url "accounts:delete" %}" method="POST">
{% csrf_token %}
<input type="submit" value="회원탈퇴"></input>
</form>
회원 정보 수정
- 기본 User Model에 대한 기본적인 수정 ModelForm 제공합니다.
- UserChangeForm
- 기본 User Model에 대한 Form을 제공합니다.
구현하기
- accounts/urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
...
path("update/", views.update, name="update"),
]
2. accounts/views.py (개요)
from django.views.decorators.http import require_http_methods
from django.contrib.auth.forms import (
...
UserChangeForm,
)
...
@require_http_methods(["GET", "POST"])
def update(request):
if request.method == "POST":
pass
else:
form = UserChangeForm(instance=request.user)
context = {"form": form}
return render(request, "accounts/update.html", context)
3. accounts/templates/accounts/update.html
{% extends "base.html" %}
{% block content %}
<h1>회원정보수정</h1>
<form action="{% url 'accounts:update' %}" method="POST">
{{ form.as_p }}
{% csrf_token %}
<button type="submit">수정하기</button>
</form>
{% endblock %}
4. base.html (버튼만들기)
(update) base.html
<a href="{% url "accounts:update" %}">회원정보수정</a>
💡 의도한 대로 되긴 되는데 … 유저가 수정하면 안될 정보까지 다 보이네요
→ 필요한 기능이 있지만 내가 커스텀 하고 싶다면?
→ 상속을 통한 Form 커스텀 👍
CustomUserChangeForm 만들기
accounts/forms.py
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = # 적어야하는데 모르겠단말이지
- get_user_model()
- 현재 프로젝트에서 활성화 되어있는 유저모델을 반환합니다.
- 직접 User 모델을 import 할 수 있지만 get_user_model 을 사용하기를 권장하고 있습니다!
- django는 다중 User 모델을 지원하므로 확장에 용이합니다.
- 프로젝트의 유연성과 확장성을 높여줍니다.
🥸 우리가 작성한 forms.py 내부의 fields에는 어떤 값들이 들어갈까요?
- UserChangeForm
User Model
AbstractUser
→ 아 ~ 여기있네요!
→ fields에는 보시는 것처럼 first_name, email… 등의 필드들이 들어갈 수 있습니다!
→ 공식문서에도 잘나와있습니다!
(https://docs.djangoproject.com/en/4.2/ref/contrib/auth/#user-model)
(update) accounts/forms.py
from django.contrib.auth.forms import UserChangeForm
from django.contrib.auth import get_user_model
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = (
"username",
"email",
"first_name",
"last_name",
)
accounts/views.py 완성시키기
@require_http_methods(["GET", "POST"])
def update(request):
if request.method == "POST":
form = CustomUserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect("index")
else:
form = CustomUserChangeForm(instance=request.user)
context = {"form": form}
return render(request, "accounts/update.html", context)
비밀번호변경
PasswordChangeForm
- 유저의 비밀번호를 변경할 수 있는 Form을 제공
구현하기
1. (password)urls
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns = [
...
path("password/", views.change_password, name="change_password"),
]
2. (password)views (1차)
{% extends "base.html" %}
{% block content %}
<h1>비밀번호 변경</h1>
<form action="{% url 'accounts:change_password' %}" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">비밀번호 변경</button>
</form>
{% endblock content %}
잘 나오는 것 같네요!
그런데, 회원정보수정의 링크를 보면 …
- 유저가 바꾸면 안되는 정보까지도 수정할 수 있게 뜬다.
- 패스워드 변경 후 돌아가는 페이지도 우리가 원하는 경로로 커스텀하고 싶다 ! /accounts/password/
- → 오버라이딩(Overriding)
- CustomUserUpdateForm
- 상속받고 있는 기존 UserChangeForm을 살펴봅시다.
오버라이딩해서 수정하기
(password) CustomUserChangeForm
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = (
"username",
"email",
"first_name",
"last_name",
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.fields.get("password"):
password_help_text = (
"You can change the password " '<a href="{}">here</a>.'
).format(f"{reverse('accounts:change_password')}")
self.fields["password"].help_text = password_help_text
UserChangeForm이것을 상속받아서 커스텀해보자.
다른 건 다 괜찮고, 필드가 들어있는 Meta 클래스만 바꾸면 된다.
from django.contrib.auth.models import user
하고 model = User을 해도 되지만,
장고에서는 앱마다 다른 유저, 즉 멀티유저 시스템을 제공한다.
그래서 다른 방법을 권장하고 있다.
→ 현재 활성화된 유저를 가져오는 방법 → get_user_model()
→ firstname, lastname, email으로만 오버라이딩 해줬는데, 패스워드도 보인다!
→ 그이유는, UserChangeForm 에서, pw는 Meta의 field가 아닌 form에서 따로 지정해주기 때문.
→ 안보여주고 싶으면 password자체를 오버라이딩해주면된다. (password = None)
__init__을 오버라이드 해주면,
부모의 __init__이 먼저 실행 된후,
우리가 오버라이딩한 __init__이 실행됨.
reverse: url_name으로부터 url를 찾아가는것
(url_name줄테니까 너가 이거보고 찾아서 알아서 url 넣어줘!)
views 완성하기
(password) views (2차)
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect("index")
else:
form = PasswordChangeForm(request.user)
context = {"form": form}
return render(request, "accounts/change_password.html", context)
그런데 비밀번호를 한 번 변경해보면 … !
비밀번호를 변경하면 기존 세션의 인증 정보와 일치하지 않기때문에 로그인이 풀리게 됩니다.
✔️ 공식문서가 답입니다 여러분
https://docs.djangoproject.com/en/4.2/topics/auth/default/#session-invalidation-on-password-change
완성
(password) views (완성)
@login_required
@require_http_methods(["GET", "POST"])
def change_password(request):
if request.method == "POST":
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
form.save()
update_session_auth_hash(request, form.user)
return redirect("index")
else:
form = PasswordChangeForm(request.user)
context = {"form": form}
return render(request, "accounts/change_password.html", context)
회원정보 수정해서 비밀번호를 바꾸면
쿠키에 있는 세션아이디로 접근하는 유저의 정보와, 비밀번호가 변경된 후의 정보가 일치하지 않아 로그아웃이 된다.
update_session_auth_hash → 하면 로그인 유지된다.
관리자도구에서 확인해보면 세션아이디는 새로 바뀐것이 확인됨.
'스파르타 내일 배움 캠프 AI 웹개발 과정 > Django framework' 카테고리의 다른 글
Django Admin (1) | 2024.09.12 |
---|---|
Django Static & Media (0) | 2024.09.12 |
Pydantic란? 사용법 / Serializer와 비교 (0) | 2024.09.10 |
Redis (0) | 2024.09.10 |
배포하기 (0) | 2024.09.04 |