지난 이야기🌿
7주 차에는 장고(Django)에서 CRUD기능을 구현했다.
8주 차(2021.05.17-2021.05.20)
8주 차에는 프로젝트에 새 앱을 만들어 회원가입, 로그인, 로그아웃 기능을 만들었다. 그리고 모델에 Comment 클래스를 추가해 댓글 기능을 추가했다. 이번 포스팅에서는 회원가입, 로그인, 로그아웃 기능을 만들어보자.
1. 새로운 앱 만들기
- 유저 관련 기능을 담당할 새로운 앱 accounts를 만들었다.
- 기능별로 앱을 만들면 유지 보수하기 좋다.
$ python manage.py startapp accounts
앱을 만든 후에는 꼭 프로젝트 폴더 settings.py에 아래와 같이 등록해주자.
#settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main',
'accounts',
]
2. urls.py - views.py - templates
1) urls.py
- 지난 주차 까지는 프로젝트 폴더의 urls.py에서 모든 url을 관리했다.
- 앱 별로 효율적인 url 관리를 위해 include를 활용해 urls.py를 분리해보자.
- 각각의 앱에 urls.py를 만들고 아래와 같이 include를 사용하면 프로젝트의 urls.py와 연결할 수 있다.
#firstproject/urls.py
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/',include('accounts.urls')),
path('',include('main.urls')),
]
* 프로젝트(firstproject)에 앱(main, accounts) 연결
#main/urls.py
from django.urls import path
from . import views
app_name="main"
urlpatterns = [
path('', views.index, name='index'),
path('create/', views.create, name='create'),
path('detail/<int:write_id>', views.detail, name='detail'),
path('update/<int:write_id>', views.update, name='update'),
path('delete/<int:write_id>', views.delete, name='delete'),
]
* 게시판 기능(CRUD)을 가진 main 앱
#accounts/urls.py
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns=[
path('signup/',views.signup, name='signup'),
path('login/', views.login, name='login'),
path('logout/', views.logout, name='logout'),
]
url을 분리하면 url name을 사용하는 템플릿 파일과 views.py를 수정해줘야 한다.
#main/views.py
def create(request):
if request.method == "POST":
create_form = WriteForm(request.POST)
if create_form.is_valid():
create_form.save()
return redirect('main:index') #index에서 main:index로 변경
else:
create_form = WriteForm()
<!-- main/templates/index.html -->
···
{% for write in all_write %}
<div class="all_write">
<a href = "{% url 'main:detail' write.id %}">
<div>{{write.id}}</div><br>
<div>{{write.title}}</div><br>
<div>{{write.contents}}</div><br>
<div>{{write.updated_at|date:"Y.m.d"}}</div><br>
<a>
</div>
{% endfor %}
···
2) views.py
장고의 auth 기능에서 제공하는 User 객체를 사용했다.
#accounts/views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from django.contrib import auth
# Create your views here.
def signup(request):
if request.method == "POST":
if request.POST["password"] == request.POST["password2"]:
user = User.objects.create_user(
username=request.POST['username'], password=request.POST['password'],
)
user.save()
auth.login(request,user)
return redirect('main:index')
else:
return render(request,'signup.html')
def login(request):
if request.method == "POST":
username = request.POST["username"]
password = request.POST["password"]
user = auth.authenticate(request, username=username, password=password)
if user is not None:
auth.login(request,user)
return redirect('main:index')
else:
message = '아이디 혹은 비밀번호가 틀렸습니다'
return render(request, 'login.html', {'message':message})
else:
return render(request, 'login.html')
def logout(request):
auth.logout(request)
return redirect('main:index')
3) accounts/signup.html
{% extends 'base.html' %}
{% block title %}회원가입{% endblock %}
{% block content %}
<form method="POST" action="{% url 'accounts:signup'%}">
{% csrf_token %}
<label for="username">아이디:</label>
<input type="text" name="username">
<label for="password">비밀번호:</label>
<input type="password" name="password">
<label for ="password2">비밀번호 확인:</label>
<input for="password2" name="password2">
<button type="submit">회원가입하기</button>
</form>
{% endblock %}
- "POST"요청에 대해 장고에서 기본으로 제공하는 보안 수단인 {% csrf_token %} 태그 사용
- <label>과 <input> 태그를 사용하여 아이디, 비밀번호, 비밀번호 확인 구현
* <label> 요소의 for 속성 값은 결합하고자 하는 요소의 id 속성 값과 같아야 한다.
4) accounts/login.html
{% extends 'base.html' %}
{% block title %}로그인{% endblock %}
{% block content %}
{% if message %}
<h1>{{message}}</h1>
{% endif %}
<form method="POST" action="{% url 'accounts:login'%}">
{% csrf_token %}
<label for="username">아이디:</label><br>
<input type="text" name="username"><br>
<label for="password">비밀번호:</label><br>
<input type="text" name="password"><br>
<button type="submit">로그인</button>
</form>
{% endblock %}
user 값이 None인 경우 만들었던 메시지(views.py) 출력
base.html
base를 사용해 templates를 관리하면 페이지를 이동해도 계속 존재하는 것들(nav bar 등)을 반복해서 작성하지 않아도 된다.
#base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Document{% endblock %}</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
#base.html 활용
{% extends 'base.html' %} #base.html 상속받기
{% block static %}
<!-- static 코드(css 파일 연결 등) 작성 -->
{% endblock %}
{% block content %}
<!-- 내용 작성 -->
{% endblock %}
3. index.html 수정
- 웹페이지 첫 화면(index.html)에서 로그인, 회원가입, 로그아웃 기능을 사용할 수 있도록 버튼으로 연결했다.
- 유저 정보를 확인할 수 있도록 views.py의 index 함수에 user 변수를 추가하고 html 파일에서 표시했다.
#main/views.py
···
def index(request):
user = request.user
all_write = Write.objects.all()
return render(request, 'index.html', {'all_write':all_write, 'user':user})
···
<!-- main/templates/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Donghae Blog</h1>
<h2>{{user}}</h2>
<button type="submit" class="create_btn"><a href="{% url 'accounts:login'%}">로그인</a></button>
<button type="submit" class="create_btn"><a href="{% url 'accounts:signup'%}">회원가입</a></button>
<button type="submit" class="create_btn"><a href="{% url 'accounts:logout'%}">로그아웃</a></button>
<div class="create_write">
<a href="{% url 'main:create'%}"><div class="create_btn">🙋♂️글쓰기🙋♂️</div></a>
</div>
{% for write in all_write %}
<div class="all_write">
<a href = "{% url 'main:detail' write.id %}">
<div>{{write.id}}</div><br>
<div>{{write.title}}</div><br>
<div>{{write.contents}}</div><br>
<div>{{write.updated_at|date:"Y.m.d"}}</div><br>
<a>
</div>
{% endfor %}
</body>
</html>
마지막으로 결과 확인!
다음 글은 댓글 쓰기,,,🦁🔥
참고자료
'LIKELION 9th' 카테고리의 다른 글
[Django] 템플릿 상속 및 css 파일 적용하기(feat. 내비게이션 바) (0) | 2021.05.29 |
---|---|
[멋쟁이 사자처럼] Django로 블로그 만들기3 (댓글 쓰기) (0) | 2021.05.25 |
[멋쟁이 사자처럼] Django로 블로그 만들기(CRUD 기능 구현하기) (0) | 2021.05.16 |
[멋쟁이 사자처럼] 장고 시작하기(단어 수 세기 예제✔) (0) | 2021.05.08 |
[멋쟁이 사자처럼] 멋사 9기 아이디에이션(feat. 예비 집사를 위한 웹사이트😺) (0) | 2021.04.30 |