Accountapp implementation
21강. 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
복사
•
model = User : 장고 기본 제공 model
•
form_class = UserCreationForm : 장고 기본 제공 form
•
success_url = reverse_lazy(' ') : 계정 생성 성공 시, 어느 경로로 연결 될 건지? (※ def는 reverse 사용, class는 reverse_lazy 사용)
•
template_name = ' ' : 어느 html 파일을 통해서 볼 건지?
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
복사
22강. 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
복사
23강. 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
복사
24강. DetailView를 이용한 개인 페이지 구현
학습 목표 : DetailView를 이용하여 개인 페이지를 만들어 본다.
ReadView = 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
복사
25강. 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
복사
26강. 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
복사
Authentication
27강. Authentication 인증 시스템 구축
학습 목표 : 요청을 보내는 유저가 로그인을 했는지, 또 접근하는 페이지의 성격에 따라 해당 페이지의 유저 객체와 요청 유저 객체를 비교하고, 필요할 경우 요청을 차단하는 코드를 구축한다.
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
from django.http import HttpResponseForbidden
def hello_world(request):
class AccountCreateView(CreateView):
class AccountDetailView(DetailView):
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
# 로그인 되어 있을 때만 Update 가능 + 타 계정으로는 접속 불가능
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
# 로그인 되어 있을 때만 Delete 가능 + 타 계정으로는 접속 불가능
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
Python
복사
28강. Decorator를 이용한 코드 간소화
학습 목표 : 파이썬의 Decorator 패턴을 이용해 자주 쓰이는 코드들을 줄여본다. 장고에서 기본 제공하는 Decorator부터 커스터마이징 한 Decorator로 27강에서 만든 인증시스템 코드 볼륨을 줄인다.
함수의 내부를 변경시키지는 않지만, 함수를 앞 뒤로 꾸며주는 역할을 한다.
Function
1) Decorator 적용 전
...
def hello_world(request):
if request.user.is_authenticated:
if request.method == "POST":
temp = request.POST.get('hello_world_input')
new_hello_world = HelloWorld()
new_hello_world.text = temp
new_hello_world.save()
hello_world_list = HelloWorld.objects.all()
return HttpResponseRedirect(reverse('accountApp:hello_world'))
else:
hello_world_list = HelloWorld.objects.all()
return render(request, 'accountApp/hello_world.html', context={'hello_world_list': hello_world_list})
else:
return HttpResponseRedirect(reverse('accountApp:login'))
...
Python
복사
2) Decorator 적용 후 (장고 기본 제공)
from django.contrib.auth.decorators import login_required
...
@login_required
def hello_world(request):
if request.method == "POST":
temp = request.POST.get('hello_world_input')
new_hello_world = HelloWorld()
new_hello_world.text = temp
new_hello_world.save()
hello_world_list = HelloWorld.objects.all()
return HttpResponseRedirect(reverse('accountApp:hello_world'))
else:
hello_world_list = HelloWorld.objects.all()
return render(request, 'accountApp/hello_world.html', context={'hello_world_list': hello_world_list})
...
Python
복사
Method (class 내부)
1) Decorator 적용 전
...
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
Python
복사
2) Decorator 적용 후 (장고 기본 제공)
※ @method_decorator(function, ‘적용할 method’)
: 일반 function에 사용하는 decorator를 method에 사용할 수 있도록 변환해주는 decorator
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
...
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
Python
복사
직접 만든 Decorator 적용하기
1) pragmatic/accountApp/decorators.py (decorators.py 생성)
from django.contrib.auth.models import User
from django.http import HttpResponseForbidden
# (get, post 모두) pk를 확인해서, User.objects가 실제 request를 보낸 유저와 같은지 판별
def account_ownership_required(func):
def decorated(request, *args, **kwargs):
# 요청을 받으면서 pk(primary key)로 'pk' 값을 가지고 있는 유저가 user가 된다.
user = User.objects.get(pk=kwargs['pk'])
# user를 확인해서, 다른 경우 Forbidden 된다.
if not user == request.user:
return HttpResponseForbidden()
return func(request, *args, **kwargs)
return decorated
Python
복사
2) Decorator 적용 후 1 (직접 만든 Decorator 적용)
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from accountApp.decorators import account_ownership_required
...
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
@method_decorator(account_ownership_required, 'get')
@method_decorator(account_ownership_required, 'post')
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
@method_decorator(account_ownership_required, 'get')
@method_decorator(account_ownership_required, 'post')
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
Python
복사
3) Decorator 적용 후 2 (직접 만든 Decorator 적용, 코드 간소화)
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from accountApp.decorators import account_ownership_required
# 배열로 만든다. (method_decorator에 넣으면, 배열 내에 있는 decorator들을 다 확인함)
has_ownership = [account_ownership_required, login_required()]
...
@method_decorator(has_ownership, 'get')
@method_decorator(has_ownership, 'post')
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountApp:hello_world')
template_name = 'accountApp/update.html'
@method_decorator(has_ownership, 'get')
@method_decorator(has_ownership, 'post')
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountApp:login')
template_name = 'accountApp/delete.html'
Python
복사
29강. superuser, media 관련 설정
학습 목표 : createsuperuser 명령어를 통한 관리자 계정 생성, 그리고 Media 파일을 다루기 위해 필요한 설정들을 진행한다.
1) superuser(관리자) 계정 생성
jangs@DESKTOP-70KJSMB MINGW64 ~/PycharmProjects/pragmatic_2/pragmatic (master)
$ python manage.py createsuperuser
Username (leave blank to use 'jangs'): username입력
Email address: (생략 가능)
Password: password 입력
Password (again): password 입력
Superuser created successfully.
2) pragmatic/pragmatic/settings.py
step 1. 하단에 MEDIA_URL과 MEDIA_ROOT를 추가한다.
...
STATIC_URL = 'static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_DIRS = [
BASE_DIR / "static",
]
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
LOGIN_REDIRECT_URL = reverse_lazy('accountApp:hello_world')
LOGOUT_REDIRECT_URL = reverse_lazy('accountApp:login')
# 실제 미디어 파일에 접근하기 위해, 주소창에서 media ~(이하) 필요하다.
MEDIA_URL = '/media/'
# 미디어 파일을 서버에 올렸을 때, 어느 경로에 지정될 것인지에 대한 정보
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Python
복사
step 2. 터미널 창에서 $ pip install pillow 를 입력하여 설치한다.
Profileapp Implementation
30강. Profileapp 시작 그리고 ModelForm
학습 목표 : 새로운 앱 Profileapp을 시작한다. 그리고 모델 기반으로 간편하게 Form을 만들어 주는 ModelForm을 짚고 넘어간다.
Profileapp 시작
•
account 앱과 profile 객체를 1:1로 매칭 시킨다. (즉, account 하나에 하나의 profile)
•
Profile Image / Profile Nickname / Profile Message 세 가지로 구성된다.
•
Delete View와 Detail View는 구현하지 않는다.
1) profileApp 생성
터미널 창에 $ python manage.py startapp profileApp 를 입력한다.
2) pragmatic/pragmatic/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',
# 추가한다.
'profileApp',
]
Python
복사
3) pragmatic/pragmatic/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('accountApp.urls')),
# profiles 경로를 추가한다.
path('profiles/', include('profileApp.urls')),
]
Python
복사
3) pragmatic/profileAPP/urls.py (urls.py 생성)
app_name = 'profileApp'
urlpatterns = [
# 추가로 작성할 것
]
Python
복사
4) pragmatic/profileAPP/models.py
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
image = models.ImageField(upload_to='profile/', null=True)
nickname = models.CharField(max_length=20, unique=True, null=True)
message = models.CharField(max_length=100, null=True)
Python
복사
5) pragmatic/profileAPP/forms.py (forms.py 생성)
from django.forms import ModelForm
from profileApp.models import Profile
class ProfileCreationForm(ModelForm):
class Meta:
model = Profile
fields = ['image', 'nickname', 'message']
Python
복사