6-5. Account 어플리케이션 작성
INFO
회원가입, 로그인, 로그아웃 기능
6-5-1. Account 어플리케이션 만들기
- startapp accounts 생성
windows command
C:\hyungsik74\pycharm\dstagram-project> python manage.py startapp accounts
linux command
$/home/hyungsik74/pycharm/dstagram-project> python manage.py startapp accounts
그림6-5-3
- config/setting.py 추가
py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'photo',
'accounts', #accounts app 추가
]
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'photo',
'accounts', #accounts app 추가
]
6-5-2. 로그인, 로그아웃 기능 추가
1. URL 추가
py
from django.urls import path
from django.contrib.auth import views as auth_view
from .views import *
# http://127.0.0.1:8000/accounts/profile/
# 1. profile 만들기
# 2. profile 페이지가 아닌 페이지로 보내기(a. 장고 설정변경, b. 웹 서버에서 설정)
urlpatterns = [
path('login/', auth_view.LoginView.as_view(), name="login"),
path('logout/', auth_view.LogoutView.as_view(template_name='registration/logout.html'), name="logout"),
path('register/', register, name='register'),
]
from django.urls import path
from django.contrib.auth import views as auth_view
from .views import *
# http://127.0.0.1:8000/accounts/profile/
# 1. profile 만들기
# 2. profile 페이지가 아닌 페이지로 보내기(a. 장고 설정변경, b. 웹 서버에서 설정)
urlpatterns = [
path('login/', auth_view.LoginView.as_view(), name="login"),
path('logout/', auth_view.LogoutView.as_view(template_name='registration/logout.html'), name="logout"),
path('register/', register, name='register'),
]
py
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('photo.urls')),
# accounts 부분 추가
path('accounts/', include('accounts.urls')),
]
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('photo.urls')),
# accounts 부분 추가
path('accounts/', include('accounts.urls')),
]
2. templates/base.html 수정
- config/setting.py LOGIN_REDIRECT_URL = '/'
html
<div class="container">
<header class="header clearfix">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Dstagram</a>
<ul class="nav">
<li class="nav-item"><a href="/" class="active nav-link ">Home</a></li>
<!-- 아래와 같이 수정합니다. -->
{% if user.is_authenticated %}
<li class="nav-item"><a href="#" class="nav-link">Welcome, {{user.get_username}}</a></li>
<li class="nav-item"><a href="{% url 'photo:photo_upload' %}" class="nav-link">Upload</a></li>
<li class="nav-item"><a href="{% url 'logout' %}" class="nav-link">Logout</a></li>
{% else %}
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link">Login</a></li>
<li class="nav-item"><a href="{% url 'register' %}" class="nav-link">Signup</a></li>
{% endif %}
</ul>
</nav>
</header>
{% block content %}
{% endblock %}
<footer class="footer">
<p>© 2023 Powered By Django.</p>
</footer>
</div>
<div class="container">
<header class="header clearfix">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Dstagram</a>
<ul class="nav">
<li class="nav-item"><a href="/" class="active nav-link ">Home</a></li>
<!-- 아래와 같이 수정합니다. -->
{% if user.is_authenticated %}
<li class="nav-item"><a href="#" class="nav-link">Welcome, {{user.get_username}}</a></li>
<li class="nav-item"><a href="{% url 'photo:photo_upload' %}" class="nav-link">Upload</a></li>
<li class="nav-item"><a href="{% url 'logout' %}" class="nav-link">Logout</a></li>
{% else %}
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link">Login</a></li>
<li class="nav-item"><a href="{% url 'register' %}" class="nav-link">Signup</a></li>
{% endif %}
</ul>
</nav>
</header>
{% block content %}
{% endblock %}
<footer class="footer">
<p>© 2023 Powered By Django.</p>
</footer>
</div>
3. login, logout HTML 생성
- accounts/templates/registration/login.html
- accounts/templates/registration/logout.html
html
{% extends 'base.html' %}
{% block title %}- Login{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Please enter your login information.</div>
<form action="" method="post">
{{form.as_p}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="Login">
</form>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}- Login{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Please enter your login information.</div>
<form action="" method="post">
{{form.as_p}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="Login">
</form>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
html
{% extends 'base.html' %}
{% block title %}- Logout{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">You have been successfully logged out.</div>
<a class="btn btn-primary" href="{% url 'login'%}">Click to Login</a>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}- Logout{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">You have been successfully logged out.</div>
<a class="btn btn-primary" href="{% url 'login'%}">Click to Login</a>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
4. setting.py 수정
- config/setting.py LOGIN_REDIRECT_URL = '/'
py
# reverse_lazy 함수를 사용해서 다른 뷰를 적용할 수 있다.
LOGIN_REDIRECT_URL = '/'
# reverse_lazy 함수를 사용해서 다른 뷰를 적용할 수 있다.
LOGIN_REDIRECT_URL = '/'
6-5-3. 회원가입기능
- 신규 및 수정이 필요한 파일 목록
1) accounts/forms.py
2) accounts/views.py
3) accounts/urls.py
4) accounts/templates/registration/register.html
5) accounts/templates/registration/register_done.html
6) templates/base.html
1) accounts/forms.py
2) accounts/views.py
3) accounts/urls.py
4) accounts/templates/registration/register.html
5) accounts/templates/registration/register_done.html
6) templates/base.html
- accounts/forms.py
py
from django.contrib.auth.models import User
from django import forms
# 폼 : 폼태그 -> HTML의 태그 -> 프론트단에서 사용자의 입력을 받는 인터페이스
# 장고의 폼 : HTML의 폼 역할, 데이터 베이스에 저장할 내용을 형식, 제약조건
class RegisterForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email']
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords not matched!')
return cd['password2']
from django.contrib.auth.models import User
from django import forms
# 폼 : 폼태그 -> HTML의 태그 -> 프론트단에서 사용자의 입력을 받는 인터페이스
# 장고의 폼 : HTML의 폼 역할, 데이터 베이스에 저장할 내용을 형식, 제약조건
class RegisterForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat Password', widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email']
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords not matched!')
return cd['password2']
- accounts/views.py
py
from django.shortcuts import render
from .forms import RegisterForm
# Create your views here.
# CRUD Create, Update
def register(request):
if request.method == "POST":
# 회원 가입 데이터 입력 완료
user_form = RegisterForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
return render(request, 'registration/register_done.html',{'new_user':new_user})
else:
# 회원 가입 내용을 입력하는 상황
user_form = RegisterForm()
return render(request, 'registration/register.html', {'form':user_form})
from django.shortcuts import render
from .forms import RegisterForm
# Create your views here.
# CRUD Create, Update
def register(request):
if request.method == "POST":
# 회원 가입 데이터 입력 완료
user_form = RegisterForm(request.POST)
if user_form.is_valid():
new_user = user_form.save(commit=False)
new_user.set_password(user_form.cleaned_data['password'])
new_user.save()
return render(request, 'registration/register_done.html',{'new_user':new_user})
else:
# 회원 가입 내용을 입력하는 상황
user_form = RegisterForm()
return render(request, 'registration/register.html', {'form':user_form})
- accounts/urls.py
py
from django.urls import path
from django.contrib.auth import views as auth_view
from .views import *
# http://127.0.0.1:8000/accounts/profile/
# 1. profile 만들기
# 2. profile 페이지가 아닌 페이지로 보내기(a. 장고 설정변경, b. 웹 서버에서 설정)
urlpatterns = [
path('login/', auth_view.LoginView.as_view(), name="login"),
path('logout/', auth_view.LogoutView.as_view(template_name='registration/logout.html'), name="logout"),
path('register/', register, name='register'),
]
from django.urls import path
from django.contrib.auth import views as auth_view
from .views import *
# http://127.0.0.1:8000/accounts/profile/
# 1. profile 만들기
# 2. profile 페이지가 아닌 페이지로 보내기(a. 장고 설정변경, b. 웹 서버에서 설정)
urlpatterns = [
path('login/', auth_view.LoginView.as_view(), name="login"),
path('logout/', auth_view.LogoutView.as_view(template_name='registration/logout.html'), name="logout"),
path('register/', register, name='register'),
]
- accounts/templates/registration/register.html
py
{% extends 'base.html' %}
{% block title %}- Registration{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Please enter your account information.</div>
<form action="" method="post">
{{form.as_p}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="Register">
</form>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}- Registration{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Please enter your account information.</div>
<form action="" method="post">
{{form.as_p}}
{% csrf_token %}
<input class="btn btn-primary" type="submit" value="Register">
</form>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
- accounts/templates/registration/register_done.html
py
{% extends 'base.html' %}
{% block title %}- Registration Done{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Registration Success. Welcome, {{new_user.username}}</div>
<a class="btn btn-info" href="/">Move to main</a>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}- Registration Done{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<div class="alert alert-info">Registration Success. Welcome, {{new_user.username}}</div>
<a class="btn btn-info" href="/">Move to main</a>
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
- templates/base.html
py
<div class="container">
<header class="header clearfix">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Dstagram</a>
<ul class="nav">
<li class="nav-item"><a href="/" class="active nav-link ">Home</a></li>
{% if user.is_authenticated %}
<li class="nav-item"><a href="#" class="nav-link">Welcome, {{user.get_username}}</a></li>
<li class="nav-item"><a href="{% url 'photo:photo_upload' %}" class="nav-link">Upload</a></li>
<li class="nav-item"><a href="{% url 'logout' %}" class="nav-link">Logout</a></li>
{% else %}
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link">Login</a></li>
<li class="nav-item"><a href="{% url 'register' %}" class="nav-link">Signup</a></li>
{% endif %}
</ul>
</nav>
</header>
{% block content %}
{% endblock %}
<footer class="footer">
<p>© 2020 Baepeu. Powered By Django 3</p>
</footer>
</div>
<div class="container">
<header class="header clearfix">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Dstagram</a>
<ul class="nav">
<li class="nav-item"><a href="/" class="active nav-link ">Home</a></li>
{% if user.is_authenticated %}
<li class="nav-item"><a href="#" class="nav-link">Welcome, {{user.get_username}}</a></li>
<li class="nav-item"><a href="{% url 'photo:photo_upload' %}" class="nav-link">Upload</a></li>
<li class="nav-item"><a href="{% url 'logout' %}" class="nav-link">Logout</a></li>
{% else %}
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link">Login</a></li>
<li class="nav-item"><a href="{% url 'register' %}" class="nav-link">Signup</a></li>
{% endif %}
</ul>
</nav>
</header>
{% block content %}
{% endblock %}
<footer class="footer">
<p>© 2020 Baepeu. Powered By Django 3</p>
</footer>
</div>
6-5-4. 댓글 기능 구현하기
기존에 구현되어 있는 댓글 앱 (disqus)
- python -m pip install django-disqus
windows command
C:\hyungsik74\pycharm\dstagram-project> python -m pip install django-disqus
C:\hyungsik74\pycharm\dstagram-project> python -m pip install six
linux command
$/home/hyungsik74/pycharm/dstagram-project> python -m pip install django-disqus
$/home/hyungsik74/pycharm/dstagram-project> python -m pip install six
- config/setting.py
py
INSTALLED_APPS = [
...
# 추가 부분
'disqus',
'django.contrib.sites',
]
# 추가 부분
DISQUS_WEBSITE_SHORTNAME = 'dstagram-django3'
SITE_ID = 1
INSTALLED_APPS = [
...
# 추가 부분
'disqus',
'django.contrib.sites',
]
# 추가 부분
DISQUS_WEBSITE_SHORTNAME = 'dstagram-django3'
SITE_ID = 1
- python manage.py migrate
windows command
C:\hyungsik74\pycharm\dstagram-project> python manage.py migrate
linux command
$/home/hyungsik74/pycharm/dstagram-project> python manage.py migrate
- photo/templates/photo/detail.html 수정
html
{% extends 'base.html' %}
{% block title %}
{{object.text|truncatechars:10}}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<p><img src="{{object.photo.url}}" style="width:100%;"></p>
<button type="button" class="btn btn-xs btn-info">
{{object.author.username}}
</button>
<p>{{object.text|linebreaksbr}}</p>
<a href="{% url 'photo:photo_delete' pk=object.id %}" class="btn btn-outline-danger btn-sm float-right">Delete</a>
<a href="{% url 'photo:photo_update' pk=object.id %}" class="btn btn-outline-success btn-sm float-right">Update</a>
</div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
{% load disqus_tags %}
{% disqus_show_comments %}
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
{% extends 'base.html' %}
{% block title %}
{{object.text|truncatechars:10}}
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8 panel panel-default">
<p><img src="{{object.photo.url}}" style="width:100%;"></p>
<button type="button" class="btn btn-xs btn-info">
{{object.author.username}}
</button>
<p>{{object.text|linebreaksbr}}</p>
<a href="{% url 'photo:photo_delete' pk=object.id %}" class="btn btn-outline-danger btn-sm float-right">Delete</a>
<a href="{% url 'photo:photo_update' pk=object.id %}" class="btn btn-outline-success btn-sm float-right">Update</a>
</div>
<div class="col-md-2"></div>
</div>
<div class="row">
<div class="col-md-2"></div>
<div class="col-md-8">
{% load disqus_tags %}
{% disqus_show_comments %}
</div>
<div class="col-md-2"></div>
</div>
{% endblock %}
- 권한제어 photo/views.py 수정
py
@login_required
def photo_list(request):
# 보여줄 사진 데이터
photos = Photo.objects.all()
return render(request, 'photo/list.html', {'photos':photos})
@login_required
def photo_list(request):
# 보여줄 사진 데이터
photos = Photo.objects.all()
return render(request, 'photo/list.html', {'photos':photos})
- 아마존 연동 Pass
아마존 AWS에 연동해서 파일을 저장하는 부분은 이 강의에서 생략하도록 하겠습니다. 추후 다른 방법으로 설명하도록 하게습니다.
- 헤로쿠
최근 헤로쿠 사이트 유로화로 인하여, 헤로쿠 연동 부분도 생략 하도록 하겠습니다. 배포 관련해서는 별도로 설명 하도록 하겠습니다.