Board App - User
게시판 만들기
django 로 게시판 만들기
Project 생성
$ mkdir board_app
$ cd board_app
$ django-admin startproject config .
$ python manage.py migrate
$ python manage.py startapp user
Settings.py 설정
INSTALLED_APPS = [
...
'user',
]
...
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
Models.py 설정
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32, verbose_name='사용자명')
password = models.CharField(max_length=64, verbose_name='비밀번호')
useremail = models.EmailField(max_length=128, verbose_name='이메일')
registered_dttm = models.DateTimeField(auto_now_add=True, verbose_name='등록일')
def __str__(self):
return self.username
class Meta:
db_table = 'board_user'
verbose_name = '사용자'
verbose_name_plural = '사용자'
$ python manage.py makemigrations
$ python manage.py migrate
Views.py 설정
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.contrib.auth.hashers import make_password, check_password
from .models import User
from .forms import LoginForm
def register(request):
if request.method == 'GET':
# 경로는 템플릿 폴더를 바라보므로 경로를 따로 표현할 필요는 없다
return render(request, 'register.html')
elif request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
re_password = request.POST.get('re-password', None)
useremail = request.POST.get('useremail', None)
# form 을 통해 넘어오는 input 속성의 name 값을 키로 사용해서 값을 얻는다.
res_data = {}
# 먼저 모든 값들이 들어와 있는지 확인을 하고 들어오지 않았을 때 아래 메시지 출력
if not (username and password and re_password and useremail):
res_data['info_error'] = '회원정보가 올바르게 입력되지 않았습니다.'
elif password != re_password:
res_data['password_error'] = '비밀번호가 다릅니다.'
else:
user = User(
username=username,
useremail=useremail,
# 장고에서는 암호화해서 저장하는 make_password 메서드를 지원해줌
# password=password가 아니라 아래처럼 더 개선된 방법으로 작성할 수 있다.
password=make_password(password) # 비밀번호를 함수 안에 전달
)
# 이렇게 하고서 저장을 하면 끝이남
user.save() # 클래스 변수 객체를 하나 생성하고 저장하면 된다..!
return render(request, 'register.html', res_data)
Urls.py 설정
from django.urls import path
from . import views
urlpatterns = [
path('register/', views.register, name='register'),
path('login/', views.login, name='login'),
path('logout/', views.logout, name='logout'),
]
Admin.py 설정
from django.contrib import admin
from .models import User
# Register your models here.
class UserAdmin(admin.ModelAdmin):
list_display = ('username', 'password')
admin.site.register(User, UserAdmin)
Forms.py 생성
user/forms.py 생성
from django import forms
from .models import User
from django.contrib.auth.hashers import check_password
class LoginForm(forms.Form):
username = forms.CharField(
error_messages={
'required': '아이디를 입력해주세요'
},
max_length=32, label="사용자 이름")
password = forms.CharField(
error_messages={
'required': '비밀번호를 입력해주세요'
},
widget=forms.PasswordInput, label="비밀번호")
# 비밀번호를 패스워드 타입으로 만들기 위해선 위젯을 직접 지정해야 한다.
# 비밀번호 일치여부 확인하는 코드
def clean(self):
cleaned_data = super().clean() # 값이 들어있지 않으면 여기서 실패처리해서 나간다.
# 값이 들어왔다는 검증이 끝나면 값을 가지고 온 후에
username = cleaned_data.get('username')
password = cleaned_data.get('password')
if username and password:
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
self.add_error('username', '아이디가 없습니다.')
return # 예외 이후 코드의 진행을 return을 통해 막음
if not check_password(password, user.password):
self.add_error('password', '비밀번호가 틀렸습니다.') # 특정 필드에 에러를 넣는 함수
else:
self.user_id = user.id # 이렇게 하면 self를 통해서 클래스 변수로 들어가고 밖에서도 접근할 수 있게 된다.
Templates 생성
user/templates 폴더 생성
Base.html
user/templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Base</title>
<!-- head 태그내에 Bootstrap 태그가 오면 된다. -->
</head>
<body>
<!-- container -->
<div class="container">
{% block contents %}
{% endblock %}
</div>
<!-- //container -->
</body>
</html>
Home.html
{% extends 'base.html' %}
{% block contents %}
<!-- Home -->
<div class="row mt-5">
<div class="col-12 text-center">
<h1>Home Page</h1>
</div>
</div>
<div class="row mt-5">
{% if request.session.user %}
<div class="col-12">
<button class="btn btn-primary btn-block" onclick="location.href='/user/logout/'">Logout</button>
</div>
{% else %}
<div class="col-6">
<button class="btn btn-primary btn-block" onclick="location.href='/user/login/'">Login</button>
</div>
<div class="col-6">
<button class="btn btn-primary btn-block" onclick="location.href='/user/register/'">Sign in</button>
</div>
{% endif %}
</div>
<div class="row mt-1">
<div class="col-12">
<button class="btn btn-primary btn-block" onclick="location.href='/board/list/'">View Post</button>
</div>
</div>
<!-- //Home -->
{% endblock %}
Login.html
{% extends 'base.html' %}
{% block contents %}
<!-- Login -->
<div class="row mt-5">
<div class="col-12 text-center">
<h1>로그인</h1>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
{{ info_error }}
{{ password_error }}
{{ password_valid }}
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<form method="post" action=".">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
<input type="{{ field.field.widget.input_type }}" class="form-control" id="{{ field.id_for_label }}"
placeholder="{{ field.label }}" name="{{ field.name }}" />
</div>
{% if field.errors %}
<span style="color: red">{{ field.errors }}</span>
{% endif %}
{% endfor %}
<button type="submit" class="btn btn-primary">로그인</button>
</form>
</div>
</div>
<!-- //Login -->
{% endblock %}
Register.html
{% extends 'base.html' %}
{% block contents %}
<div class="row mt-5">
<div class="col-12 text-center">
<h1>회원가입</h1>
</div>
</div>
<div class="row mt-5">
<div class="col-12">
{{ info_error }}
</div>
</div>
<div class="row mt-5">
<div class="col-12">
<form method="post" action=".">
{% csrf_token %}
<div class="form-group">
<label for="username">사용자 이름</label>
<input type="text" class="form-control" id="username" name="username" placeholder="사용자 이름">
</div>
<div class="form-group">
<label for="password">비밀번호</label>
<input type="password" class="form-control" placeholder="비밀번호" id="password" name="password">
{{ password_error }}
</div>
<div class="form-group">
<label for="re-password">비밀번호 확인</label>
<input type="password" class="form-control" placeholder="비밀번호 확인" id="re-password" name="re-password">
{{ password_error }}
</div>
<div class="form-group">
<label for="useremail">이메일 주소</label>
<input type="email" class="form-control" placeholder="이메일 주소" id="useremail" name="useremail">
</div>
<button type="submit" class="btn btn-primary">등록</button>
</form>
</div>
</div>
{% endblock %}
Comments