1. CreateView를 통한 회원가입 구현
학습 목표 : 장고에서 제공하는 CreateView를 통해 Account의 Create, 즉 회원 가입을 구현해 본다.
1) pragmatic/accountApp/views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from accountApp.models import HelloWorld
from django.views.generic import CreateView
def hello_world(request):
# class-Based View로 AccountCreateView를 추가한다.
class AccountCreateView(CreateView):
model = User
form_class = UserCreationForm
success_url = reverse_lazy('accountApp:hello_world') # 계정 만들기 성공 했으면, 어느 경로로 연결할 것인가?
template_name = 'accountApp/create.html' # 어느 html 파일을 통해서 볼지?
Python
복사
2) pragmatic/accountApp/urls.py
from django.urls import path
from accountApp.views import hello_world, AccountCreateView
app_name = "accountApp"
urlpatterns = [
path('hello_world/', hello_world, name='hello_world'),
# create 경로를 추가한다.
path('create/', AccountCreateView.as_view(), name='create'),
]
Python
복사
3) pragmatic/accountApp/templates/accountApp/create.html (create.html 생성)
{% extends 'base.html' %}
{% block content %}
<div style="text-align: center">
<form action="{% url 'accountApp:create' %}" method="post">
<!-- post 사용 시, 잊지 말 것! -->
{% csrf_token %}
<!-- views.py에서 지정한 class form -->
{{ form }}
<input type="submit" class="btn btn-primary">
</form>
</div>
{% endblock %}
HTML
복사
2. Login / Logout 구현
학습 목표 : 장고에서 제공되는 LoginView, LogoutView를 기반으로 로그인 및 로그아웃 기능을 구현한다.
1) pragmatic/accountApp/urls.py
from django.urls import path
from accountApp.views import hello_world, AccountCreateView
from django.contrib.auth.views import LoginView, LogoutView
app_name = "accountApp"
urlpatterns = [
path('hello_world/', hello_world, name='hello_world'),
# login과 logout 경로를 추가한다.
path('login/', LoginView.as_view(template_name='accountApp/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path('create/', AccountCreateView.as_view(), name='create'),
]
Python
복사
2) pragmatic/accountApp/templates/accountApp/login.html (login.html 생성)
{% extends 'base.html' %}
{% block content %}
<div style="text-align: center">
<div>
<h4>Login</h4>
</div>
<div>
<form action="" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-primary">
</form>
</div>
</div>
{% endblock %}
HTML
복사
3) pragmatic/pragmatic/templates/header.html
<div class="pragmatic_header">
<div>
<h1 class="pragmatic_logo">Pragmatic</h1>
</div>
<div>
<span>nav1</span>
<span>nav2</span>
<span>nav3</span>
{% if not user.is_authenticated %}
<!--유저가 로그인 되어 있지 않을 경우-->
<a href="{% url 'accountApp:login' %}?next={{ request.path }}">
<span>login</span>
</a>
{% else %}
<!--유저가 로그인 되어 있을 경우-->
<a href="{% url 'accountApp:logout' %}?next={{ request.path }}">
<span>logout</span>
</a>
{%endif %}
</div>
</div>
HTML
복사
4) pragmatic/pragmatic/settings.py
from pathlib import Path
import environ
import os
from django.urls import reverse_lazy
# 맨 하단에 Redirect 경로를 추가한다.
LOGIN_REDIRECT_URL = reverse_lazy('accountApp:hello_world')
LOGOUT_REDIRECT_URL = reverse_lazy('accountApp:login')
Python
복사
3. Bootstrap을 이용한 Form 디자인 정리
학습 목표 : django-bootstrap4 라이브러리를 이용하여 form을 부트스트랩 스타일로 꾸며보고, 지금까지 만든 사이트의 디자인을 정리한다.
1) pragmatic/pragmatic/settings.py
우선, 터미널에서 pip install django-bootstrap4 입력하여 설치한다.
그 다음 settings.py에서 내용을 추가한다.
from pathlib import Path
import environ
import os
from django.urls import reverse_lazy
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accountApp',
# 추가한다.
'bootstrap4',
]
Python
복사
2) pragmatic/accountApp/templates/accountApp/login.html
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block content %}
<!-- (문단의 스타일을 추가적으로 변경함) -->
<div style="text-align: center; max-width: 500px; margin: 4rem auto">
<div>
<h4>Login</h4>
</div>
<div>
<form action="" method="post">
{% csrf_token %}
<!-- 기존 {{ form }} 대신 bootstrap_form으로 변경한다.-->
{% bootstrap_form form %}
<input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
</form>
</div>
</div>
{% endblock %}
HTML
복사
3) pragmatic/accountApp/templates/accountApp/create.html
{% extends 'base.html' %}
<!-- 추가한다. -->
{% load bootstrap4 %}
{% block content %}
<!-- 변경한다. -->
<div style="text-align: center; max-width: 500px; margin: 4rem auto">
<div class="mb-4">
<h4>SignUp</h4>
</div>
<form action="{% url 'accountApp:create' %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
</form>
</div>
{% endblock %}
HTML
복사
4) pragmatic/templates/head.html (폰트를 전체적으로 변경하고 싶을 때)
우선, pragmatic/static 하단에 ‘fonts’라는 새 디렉토리를 생성한 후, 다운 받은 글꼴 파일을 삽입한다.
그 다음 head.html 파일에서 <style> 태그를 통해 내용을 추가한다.
{% load static %}
<head>
<meta charset="UTF-8">
<title>Pragmatic</title>
<!-- 폰트 정보를 추가한다. -->
<style>
@font-face {
font-family: 'NanumPen';
src: local('NanumPen'),
url("{% static 'fonts/NanumPen.ttf' %}") format("opentype");
}
</style>
</head>
HTML
복사
4. DetailView를 이용한 개인 페이지 구현
학습 목표 : DetailView를 이용하여 개인 페이지를 만들어 본다.
1) pragmatic/pragmatic/views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
# Create your views here.
from accountApp.models import HelloWorld
from django.views.generic import CreateView, DetailView
def hello_world(request):
class AccountCreateView(CreateView):
# AccountDetailView 클래스를 추가한다.
class AccountDetailView(DetailView):
model = User
context_object_name = 'target_user'
template_name = 'accountApp/detail.html'
Python
복사
2) pragmatic/accountApp/templates/accountApp/detail.html (detail.html 생성)
{% extends 'base.html' %}
{% block content %}
<div>
<div style="text-align: center; max-width: 500px; margin: 4rem auto;">
<p>
{{ target_user.date_joined }}
</p>
<h2 style="font-family: 'NanumPen'">
{{ target_user.username }}
</h2>
</div>
</div>
{% endblock %}
HTML
복사
3) pragmatic/accountApp/urls.py
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
from accountApp.views import hello_world, AccountCreateView, AccountDetailView
app_name = "accountApp"
urlpatterns = [
path('hello_world/', hello_world, name='hello_world'),
path('login/', LoginView.as_view(template_name='accountApp/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path('create/', AccountCreateView.as_view(), name='create'),
# detail 경로를 추가한다.
path('detail/<int:pk>', AccountDetailView.as_view(), name='detail'),
]
Python
복사
3) pragmatic/templates/header.html
<div class="pragmatic_header">
<div>
<h1 class="pragmatic_logo">Pragmatic</h1>
</div>
<div>
<span>nav1</span>
<span>nav2</span>
<span>nav3</span>
{% if not user.is_authenticated %}
<!-- 유저가 로그인 되어 있지 않을 경우 -->
{% else %}
<!-- 유저가 로그인 되어 있을 경우 -->
<!-- detail.html로 연결될 MyPage 바를 추가한다. -->
<a href="{% url 'accountApp:detail' pk=user.pk %}">
<span>MyPage</span>
</a>
<a href="{% url 'accountApp:logout' %}?next={{ request.path }}">
<span>logout</span>
</a>
{%endif %}
</div>
</div>
HTML
복사
5. UpdateView를 이용한 비밀번호 변경 구현
학습 목표 : UpdateView를 이용한 비밀번호 변경 구현을 진행한다.
1) pragmatic/accountApp/views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from accountApp.models import HelloWorld
from django.views.generic import CreateView, DetailView, UpdateView
from accountApp.forms import AccountUpdateForm
def hello_world(request):
class AccountCreateView(CreateView):
class AccountDetailView(DetailView):
# AccountCreatView 클래스를 토대로 AccountUpdateView를 추가한다.
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm # Form을 바꿔줌
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
Python
복사
2) pragmatic/accountApp/urls.py
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
from accountApp.views import hello_world, AccountCreateView, AccountDetailView, AccountUpdateView
app_name = "accountApp"
urlpatterns = [
path('hello_world/', hello_world, name='hello_world'),
path('login/', LoginView.as_view(template_name='accountApp/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path('create/', AccountCreateView.as_view(), name='create'),
path('detail/<int:pk>', AccountDetailView.as_view(), name='detail'),
# update 경로를 추가한다.
path('update/<int:pk>', AccountUpdateView.as_view(), name='update'),
]
Python
복사
3) pragmatic/accountApp/templates/accountApp/update.html (update.html 생성)
<!-- create.html 내용을 토대로 작성함 -->
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block content %}
<div style="text-align: center; max-width: 500px; margin: 4rem auto">
<div class="mb-4">
<h4>Change Info</h4>
</div>
<form action="{% url 'accountApp:update' pk=target_user.pk %}" method="post">
{% csrf_token %}
{% bootstrap_form form %}
<input type="submit" class="btn btn-dark rounded-pill col-6 mt-3">
</form>
</div>
{% endblock %}
HTML
복사
4) pragmatic/accountApp/templates/accountApp/detail.html
{% extends 'base.html' %}
{% block content %}
<div>
<div style="text-align: center; max-width: 500px; margin: 4rem auto;">
<p>
{{ target_user.date_joined }}
</p>
<h2 style="font-family: 'NanumPen'">
{{ target_user.username }}
</h2>
<!-- 로그인 했을 경우, 변경하고자 하는 유저가 본인일 경우 update 가능 (추가) -->
{% if target_user == user %}
<a href="{% url 'accountApp:update' pk=user.pk %}">
<p>
Change Info
</p>
</a>
{% endif %}
</div>
</div>
{% endblock %}
HTML
복사
5) pragmatic/accountApp/forms.py (forms.py 생성)
# update 시, id 변경을 비활성화 하기 위한 용도
from django.contrib.auth.forms import UserCreationForm
class AccountUpdateForm(UserCreationForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['username'].disabled = True
Python
복사
6. DeleteView 기반 회원 탈퇴 구현
학습 목표 : DeleteView 기반 회원 탈퇴 구현을 진행한다.
1) pragmatic/accountApp/views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from accountApp.models import HelloWorld
from django.views.generic import CreateView, DetailView, UpdateView, DeleteView
from accountApp.forms import AccountUpdateForm
def hello_world(request):
class AccountCreateView(CreateView):
class AccountDetailView(DetailView):
class AccountUpdateView(UpdateView):
# AccountDeleteView를 추가한다.
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
Python
복사
2) pragmatic/accountApp/urls.py
from django.contrib.auth.views import LoginView, LogoutView
from django.urls import path
from accountApp.views import hello_world, AccountCreateView, AccountDetailView
from accountApp.views import AccountUpdateView, AccountDeleteView
app_name = "accountApp"
urlpatterns = [
path('hello_world/', hello_world, name='hello_world'),
path('login/', LoginView.as_view(template_name='accountApp/login.html'), name='login'),
path('logout/', LogoutView.as_view(), name='logout'),
path('create/', AccountCreateView.as_view(), name='create'),
path('detail/<int:pk>', AccountDetailView.as_view(), name='detail'),
path('update/<int:pk>', AccountUpdateView.as_view(), name='update'),
# delete 경로를 추가한다.
path('delete/<int:pk>', AccountDeleteView.as_view(), name='delete'),
]
Python
복사
3) pragmatic/accountApp/templates/accountApp/delete.html (delete.html 생성)
{% extends 'base.html' %}
{% block content %}
<div style="text-align: center; max-width: 500px; margin: 4rem auto">
<div class="mb-4">
<h4>Quit</h4>
</div>
<form action="{% url 'accountApp:delete' pk=target_user.pk %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-danger rounded-pill col-6 mt-3">
</form>
</div>
{% endblock %}
HTML
복사
4) pragmatic/accountApp/templates/accountApp/detail.html
{% extends 'base.html' %}
{% block content %}
<div>
<div style="text-align: center; max-width: 500px; margin: 4rem auto;">
<p>
{{ target_user.date_joined }}
</p>
<h2 style="font-family: 'NanumPen'">
{{ target_user.username }}
</h2>
{% if target_user == user %}
<a href="{% url 'accountApp:update' pk=user.pk %}">
<p>
Change Info
</p>
</a>
<!-- Quit이 가능한 경우를 추가해 준다. -->
<a href="{% url 'accountApp:delete' pk=user.pk %}">
<p>
Quit
</p>
</a>
{% endif %}
</div>
</div>
{% endblock %}
HTML
복사
3) pragmatic/templates/header.html
<div class="pragmatic_header">
<div>
<h1 class="pragmatic_logo">Pragmatic</h1>
</div>
<div>
<span>nav1</span>
<span>nav2</span>
<span>nav3</span>
{% if not user.is_authenticated %}
<!-- 유저가 로그인 되어 있지 않을 경우 -->
<a href="{% url 'accountApp:login' %}?next={{ request.path }}">
<span>login</span>
</a>
<a href="{% url 'accountApp:create' %}">
<span>SignUp</span>
</a>
{% else %}
<!-- 유저가 로그인 되어 있을 경우 -->
<a href="{% url 'accountApp:detail' pk=user.pk %}">
<span>MyPage</span>
</a>
<a href="{% url 'accountApp:logout' %}?next={{ request.path }}">
<span>logout</span>
</a>
{%endif %}
</div>
</div>
HTML
복사