참고 사이트
보고 배운 곳
https://code1018.tistory.com/244
model, admin 설정
https://integer-ji.tistory.com/89
form을 이용한 글 수정 페이지 수정
https://integer-ji.tistory.com/102
오늘 사용한 App
myMember
설치해야 할pip
pip install django-betterforms
pip install Pillow
사용한 명령어
python manage.py createsuperuser
python manage.py makemigrations
python manage.py migrate
생성한 파일 & 폴더
myMember/templates/signup.html - 파일 생성
myMember/forms.py - 파일 생성
포인트
getbootstrap를 이용한 회원가입, 로그인 페이지 구축
usermodel의 확장
django form을 이용한 회원가입, 로그인 페이지 만들기
django에서 제공해주는 LoginView, LogoutView 사용
로그인할 때의 함수 로직
완성된 git ( 2020.06.18 키 노출로 인한 git 비공개 )
https://github.com/integerJI/int_1
aws key 노출되다.
https://integer-ji.tistory.com/200
aws key 생성시 주의 할점
https://integer-ji.tistory.com/208
사용한 디렉터리 계층구조 및 파일
myMember
<!-- myProject/myMember/templates/signup.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
</head>
<body>
<div class="mt-3 container">
{% if messages %}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
{% for message in messages %}
<strong>{{ message.message }}</strong>
{% endfor %}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
</div>
<div class="d-flex justify-content-center">
<div class="mt-5 mb-5 text-muted text-center">
<div class="card" style="width: 30rem;">
<div class="card-body">
<h3 class="card-title">Eomu Hae</h5>
<hr>
<h5 class="card-subtitle mb-2 text-muted">Sign Up</h6>
<br>
<form class="form-signin" method="POST" action="{% url 'signup'%}"
enctype="multipart/form-data">
{%csrf_token%}
<div class="form-label-group">
<input type="text" name="user-username" class="form-control" placeholder="Login Id"
maxlength="15">
<small class="text-muted">15자 이하 문자, 숫자 그리고 @/./+/-/_만 가능합니다.</small>
</div>
<br>
<div class="form-label-group">
<input type="password" name="user-password1" class="form-control"
placeholder="Password">
<small class="text-muted">비밀번호는 최소 8자 이상이어야 합니다.</small>
</div>
<br>
<div class="form-label-group">
<input type="password" name="user-password2" class="form-control"
placeholder="Confirm Password">
<small class="text-muted">비밀번호는 전부 숫자로 할 수 없습니다.</small>
</div>
<br>
<div class="form-label-group">
<textarea class="form-control" id="id_profile-intro" rows="3" name="profile-intro"
placeholder="About Me" maxlength="40"></textarea>
<small class="text-muted">40자 이하 문자만 가능합니다.</small>
</div>
<br>
<div class="form-label-group">
<input type="file" name="profile-profile_image" class="form-control-file"
accept="image/*">
<small class="text-muted">권장 크기 : 250 * 250</small>
</div>
<br>
<button type="submit" class="form-control">Sign Up</button>
</form>
<hr>
<a href="{% url 'signin' %}">
<button type="submit" class="form-control">Go back</button>
</a>
</div>
</div>
</div>
</div>
</body>
</html>
<!-- myProject/myMember/templates/signin.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
</head>
<body>
<div class="mt-3 container">
{% if messages %}
<div class="alert alert-warning alert-dismissible fade show" role="alert">
{% for message in messages %}
<strong>{{ message.message }}</strong>
{% endfor %}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
</div>
<div class="d-flex justify-content-center">
<div class="mt-5 mb-5 text-muted text-center">
<div class="card" style="width: 30rem;">
<div class="card-body">
<h3 class="card-title">Eomu Hae</h5>
<hr>
<h5 class="card-subtitle mb-2 text-muted">Sign In</h6>
<br>
<form class="form-signin" method="POST" action="{% url 'signin'%}">
{%csrf_token%}
<div class="form-label-group">
<input type="text" name="username" class="form-control" placeholder="Id">
</div>
<br>
<input type="password" name="password" class="form-control" placeholder="Password">
<br>
<button type="submit" class="form-control">Sign In</button>
</form>
<hr>
<a href="{% url 'signup' %}">
<button type="submit" class="form-control">Sign Up</button>
</a>
</div>
</div>
</div>
</div>
</body>
</html>
# myProject/myMember/admin.py
from django.contrib import admin
from .models import Profile
# Register your models here.
admin.site.register(Profile)
# myProject/myMember/forms.py
from django import forms
from django.db import models
from .models import Profile
from django.contrib.auth.models import User
from betterforms.multiform import MultiModelForm
from django.views.generic.edit import CreateView
from django.contrib.auth.forms import UserCreationForm
class DateInput(forms.DateInput):
input_type = 'date'
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ("username", "password1", "password2")
widgets = {
'username': forms.TextInput(attrs={'class': 'form-control', 'placeholder':'15자 이내로 입력 가능합니다.'}),
'password1' : forms.PasswordInput(attrs={'class': 'form-control'}),
'password2' : forms.PasswordInput(attrs={'class': 'form-control'}),
}
def save(self, commit=True):
user = super(CreateUserForm, self).save(commit=False)
if commit:
user.save()
return user
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['profile_image', 'intro',]
widgets = {
'intro': forms.TextInput(attrs={'class': 'form-control'}),
'profile_image' : forms.ClearableFileInput(attrs={'class': 'form-control-file', 'onchange': 'readURL(this);'}),
}
labels = {
'profile_image': '프로필 사진',
'intro': '인사말',
}
class UserCreationMultiForm(MultiModelForm):
form_classes = {
'user' : CreateUserForm,
'profile' : ProfileForm,
}
class LoginForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'password']
# myProject/myMember/models.py
from django.db import models
from django.contrib.auth.models import User
from betterforms.multiform import MultiModelForm
from django import forms
class Profile(models.Model):
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'Profile'
user = models.OneToOneField(User, on_delete=models.CASCADE)
nick = models.CharField(verbose_name='NickName', max_length=50, blank=True,)
intro = models.TextField(blank=True, max_length=200, )
profile_image = models.ImageField(blank=True, upload_to='usr')
def __str__(self):
return self.nick
# myProject/myMember/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('signup/', views.signup, name='signup'),
path('signin/', views.signin, name='signin'),
path('signout/', views.signout, name='signout'),
]
# myProject/myMember/views.py
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.models import User
from django.contrib import auth
from django.contrib import messages
from django.contrib.auth.views import LoginView, LogoutView
from django.contrib.auth.forms import UserCreationForm
from django.conf import settings
from django.views.generic.edit import CreateView
from django.views.generic.detail import DetailView
from django.urls import reverse_lazy
from django.views import generic, View
from django.contrib.auth.decorators import login_required
from .forms import UserCreationMultiForm, ProfileForm
from .models import Profile
def signup(request):
if request.method == 'POST':
if request.POST['user-password1'] == request.POST['user-password2']:
form = UserCreationMultiForm(request.POST, request.FILES)
if form.is_valid():
user = form['user'].save()
profile = form['profile'].save(commit=False)
profile.user = user
profile.nick = user
profile.save()
return redirect('signin')
else:
user = request.POST['user-username']
user = User.objects.get(username=user)
messages.info(request, '아이디가 중복됩니다.')
return render(request, 'signup.html')
else:
messages.info(request, '비밀번호가 다릅니다.')
return render(request, 'signup.html')
return render(request, 'signup.html')
class Loginviews(LoginView):
template_name = 'signin.html'
def form_invalid(self, form):
messages.error(self.request, '로그인에 실패하였습니다. Id 혹은 Password를 확인해 주세요.', extra_tags='danger')
return super().form_invalid(form)
signin = Loginviews.as_view()
class LogoutViews(LogoutView):
next_page = settings.LOGOUT_REDIRECT_URL
signout = LogoutViews.as_view()
myProject
# myProject/myProject/settings.py ( 추가 )
# 로그인 페이지 지정
LOGIN_URL = '/signin/'
# 로그인 완료 후 나올 페이지
LOGIN_REDIRECT_URL = 'index'
# 로그아웃 후 나올 페이지
LOGOUT_REDIRECT_URL = 'signin'
마무리
'코딩공부 > 홈페이지 만들기' 카테고리의 다른 글
Django로 홈페이지 만들기 - #5 글 수정, 글 삭제 (0) | 2020.05.04 |
---|---|
Django로 홈페이지 만들기 - #4 글 목록, 글 쓰기 (0) | 2020.05.04 |
Django로 홈페이지 만들기 - #3 stiatic, media, base.html (0) | 2020.05.04 |
Django로 홈페이지 만들기 - #1 기본설정 (0) | 2020.05.03 |
Django로 홈페이지 만들기 - 인스타그램 벤치마킹하기 (0) | 2020.05.03 |