https://github.com/JisunParkRea/djangotube_tutorial
참고
Using the Django authentication system
Django Girls Tutorial: Extensions
구현하고자 하는 기능
해당 포스트에서는 장고의 내장된 인증 기능 없이 view, urls 등을 일일이 다 구현해보았다.
- 회원가입
- username, email, password로 가입
- 회원가입 시 가입 계정으로 로그인 된 후 video list 페이지로 넘어가기
- 로그인
- 로그인 후 video list 페이지로 넘어가기
- 로그인 실패 시 login failed를 알리는 HttpResponse 보내기
- 로그아웃
- 로그아웃 후 video list 페이지로 넘어가기
- Template
- 로그인/회원가입 전에 video list 페이지 방문 시 로그인/회원가입 버튼 보여주기
- 로그인 후 video list 우측 상단에 username을 표시하고, logout 링크, new video 버튼도 같이 보여주기
- 추가적으로...
- 새로운 video는 로그인된 사용자만 추가할 수 있도록 하자(화면에 new video 버튼이 안보이더라도, url을 알고 있다면 접근이 가능하기 때문에)
회원가입
forms.py
회원가입 시 사용자에게 입력 받을 ModelForm 작성
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'password']
views.py
회원가입 로직을 구현하자
- POST request인 경우
- UserForm대로 사용자가 입력한 form을 받아서 그것이 유효하면 새로운 user을 만들고 login한 후 video_list 페이지로 redirect한다.
- POST request가 아닌 경우
- 비어있는 UserForm을 반환한다
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib.auth import login
from .forms import UserForm
def signup(request):
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
new_user = User.objects.create_user(**form.cleaned_data)
login(request, new_user)
return redirect('video_list')
else:
form = UserForm()
return render(request, 'video/user_new.html')
urls.py
urlpatterns = [
path('signup/', views.signup, name='user_signup'),
]
templates/video/user_new.html
<html>
<head>
<title>Sign up</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
</head>
<body>
<div class="content container">
<header class="page-header">
<h1>Sign up</h1>
</header>
<div class="row">
<div class="col-md-16">
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" name="email" class="form-control" id="email" placeholder="Email">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="text" name="password" class="form-control" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
로그인
forms.py
로그인 시 사용자에게 입력 받을 ModelForm 작성
class LoginForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'password']
views.py
로그인 로직을 구현하자
- POST request인 경우
- LoginForm대로 사용자가 입력한 form을 받아서 username과 password를 authenticate한다
- user이 유효하면, login하고 video_list 페이지로 redirect한다
- POST request가 아닌 경우
- 비어있는 LoginForm을 반환한다
from django.http import HttpResponse
from django.contrib.auth import authenticate
from .forms import LoginForm
def signin(request):
if request.method == 'POST':
form = LoginForm(request.POST)
username = request.POST['username']
password = request.POST['password']
user = authenticate(username = username, password = password)
if user is not None:
login(request, user)
return redirect('video_list')
else:
return HttpResponse('Login failed. Try again.')
else:
form = LoginForm()
return render(request, 'video/user_login.html')
urls.py
urlpatterns = [
path('login/', views.signin, name='user_login'),
]
templates/video/user_login.html
<html>
<head>
<title>Login</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
</head>
<body>
<div class="content container">
<header class="page-header">
<h1>Login</h1>
</header>
<div class="row">
<div class="col-md-16">
<form method="POST">
{% csrf_token %}
<div class="form-group">
<label for="username">Username</label>
<input type="text" name="username" class="form-control" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="text" name="password" class="form-control" id="password" placeholder="Password">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
</div>
</div>
</body>
</html>
로그아웃
views.py
from django.contrib.auth import logout
def signout(request):
logout(request)
return redirect('video_list')
urls.py
urlpatterns = [
path('logout/', views.signout, name='user_logout'),
]
템플릿 수정
templates/video/video_list.html
<html>
<head>
<title>Video List</title>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
</head>
<body>
<div class="content container">
<header class="page-header" sytle="overflow: auto;">
<h1 style="display: inline;">Video List</h1>
{% if user.is_authenticated %}
<a class="btn btn-default" href="/video/new" style="float: right;">New Video</a>
<p style="float: right;"><span style = " font-size:1.5em; color: green;">Welcome, {{ user.username }}<small>(<a href="{% url 'user_logout' %}">Logout</a>)</small> </span></p>
{% else %}
<div style="float: right;">
<a class="btn btn-default" href="/video/signup">Sign up</a>
<a class="btn btn-default" href="/video/login">Login</a>
</div>
{% endif %}
</header>
<div class="row">
<div class="col-md-12">
{% for video in video_list %}
<a href="/video/{{ video.id }}">
<h4>{{ video.title }}</h4>
</a>
{% endfor %}
</div>
</div>
</div>
</body>
</html>
추가적으로...
로그인된 사용자만 새로운 비디오를 추가할 수 있게 하기
login_required decorator을 해당 view에 사용하면 된다.
from django.contrib.auth.decorators import login_required
@login_required
def video_new(request):
if request.method == 'POST': # 새로운 비디오 데이터를 업로드할 때
form = VideoForm(request.POST)
form.save()
return redirect('video_list')
elif request.method == 'GET': # 새로운 비디오를 추가할 템플릿을 가져와야할 때
return render(request, 'video/video_new.html')