3주차에서 배울 것
- Django에서 제공하는 사용자 관리 기능 사용해 보기
- Django에서 제공하는 사용자 모델 확장하기
- 포스트 읽기 / 쓰기 / 삭제
Django의 사용자 모델 비교
auth_user는 장고에서 미리 생성해 준 데이터베이스 테이블
my_user는 우리가 ORM을 사용해 만든 데이터베이스 테이블
auth_user에 내용을 훨씬 많이 담을 수 있지만 bio가 없다
고로 두 테이블을 합치면 두가지 장점 모두 사용 가능!
User모델 업그레이드 하기
user/models.py:
from django.db import models
from django.contrib.auth.models import AbstractUser # 장고에서 사용하는 기본 유저모델
class UserModel(AbstractUser): # 상속
class Meta:
db_table = "my_user"
bio = models.CharField(max_length=256, default='') # 추가
mySpartaSns/settings.py:
AUTH_USER_MODEL = 'user.UserModel'
# User모델을 데이터베이스에 적용시키기
python manage.py makemigrations
python manage.py migrate
회원가입 기능 수정하기
user/views.py:
from django.shortcuts import render, redirect
from .models import UserModel
from django.http import HttpResponse
from django.contrib.auth import get_user_model # 사용자가 데이터베이스 안에 있는지 검사
def sign_up_view(request):
if request.method == 'GET':
return render(request, 'user/signup.html')
elif request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
password2 = request.POST.get('password2', None)
bio = request.POST.get('bio', None)
if password != password2:
return render(request, 'user/signup.html')
else:
exist_user = get_user_model().objects.filter(username=username) #####
if exist_user:
return render(request, 'user/signup.html')
else:
UserModel.objects.create_user(username=username, password=password, bio=bio) #####
return redirect('/sign-in')
로그인 기능 수정하기
user/views.py:
from django.shortcuts import render, redirect
from .models import UserModel
from django.http import HttpResponse
from django.contrib.auth import get_user_model
from django.contrib import auth #####
def sign_in_view(request):
if request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
me = auth.authenticate(request, username=username, password=password) #####
if me is not None: # 저장된 사용자가 존재한다면
auth.login(request, me)
return HttpResponse(me.username + "님의 로그인 성공! 환영합니다!")
else:
return redirect('/sign-in')
elif request.method == 'GET':
return render(request, 'user/signin.html')
로그인 후 페이지 이동하기
페이지 연결시 views.py에 render() 함수를 사용,
작성한 views.py 함수를 urls.py에 연결.
tweet/views.py:
from django.shortcuts import render, redirect
def home(request):
user = request.user.is_authenticated # 사용자의 로그인 확인
if user:
return redirect('/tweet')
else:
return redirect('/sign-in')
def tweet(request):
if request.method == 'GET':
return render(request, 'tweet/home.html')
tweet/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'), # 127.0.0.1:8000 과 views.py 폴더의 home 함수 연결
path('tweet/', views.tweet, name='tweet') # 127.0.0.1:8000/tweet 과 views.py 폴더의 tweet 함수 연결
]
mySpartaSns/urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('user.urls')),
path('', include('tweet.urls')), # 추가
]
user/views.py:
def sign_in_view(request):
if request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
me = auth.authenticate(request, username=username, password=password)
if me is not None:
auth.login(request, me)
return redirect('/') # 로그인하면 홈으로 가도록 수정
else:
return redirect('/sign-in')
elif request.method == 'GET':
return render(request, 'user/signin.html')
로그인 이후 기능 다듬기
templates/tweet/home.html:
<h5 class="card-title">{{ user.username }}</h5>
<p class="card-text">{{ user.bio }}</p>
templates/base.html:
<form class="">
{% if not user.is_authenticated %}
# user가 로그인되어 있지 않을 때만 Sign In, Up을 보여주겠다
# {% %} : 파이썬처럼 if문, for문 등을 작성할 수 있다
<ul class="">
...
</ul>
{% else %}
{{ user.username }} 님 반갑습니다! # 중괄호 두번으로 user의 정보 사용 가능(django)
{% endif %}
</form>
로그인 한 사람은 사용 안 해도 되는 페이지
user = request.user.is_authenticated
if user:
return redirect('/')
else:
return render(request, 'user/signin.html')
로그아웃 구현하기
user/views.py:
from django.contrib.auth.decorators import login_required
@login_required # 로그인 한 사용자만 접근할 수 있게 해주는 기능
def logout(request):
auth.logout(request)
return redirect('/')
user/views.py:
from django.urls import path
from . import views
urlpatterns = [
path('sign-up/', views.sign_up_view, name='sign-up'),
path('sign-in/', views.sign_in_view, name='sign-in'),
path('logout/', views.logout, name='logout'), # 추가
]
base.html:
{% else %}
<ul class="navbar-nav mr-auto">
<li class="nav-item disabled">
<span class="nav-link">
{{ user.username }} 님 반갑습니다!
</span>
</li>
<li class="nav-item active">
<a class="nav-link" href="/logout"> Logout <span class="sr-only"></span></a>
</li>
</ul>
{% endif %}
게시글 쓰기
templates/tweet/home.html:
<form action="/tweet/" method="POST">
{% csrf_token %}
tweet/views.py:
from django.shortcuts import render, redirect
from .models import TweetModel # 글쓰기 모델
def home(request):
user = request.user.is_authenticated # 사용자의 로그인 확인
if user:
return redirect('/tweet')
else:
return redirect('/sign-in')
def tweet(request):
if request.method == 'GET':
user = request.user.is_authenticated # 사용자의 로그인 확인
if user:
return render(request, 'tweet/home.html')
else:
return redirect('/sign-in')
elif request.method == 'POST':
user = request.user
my_tweet = TweetModel() # 글쓰기 모델 가져오기
my_tweet.author = user # 모델에 사용자 저장
my_tweet.content = request.POST.get('my-content', '') # 모델에 글 저장
my_tweet.save()
return redirect('/tweet')
게시글 읽기/삭제
게시글 읽어오기
tweet/views.py:
def tweet(request):
if request.method == 'GET': # GET 방식으로 요청
user = request.user.is_authenticated # 사용자의 로그인 확인
if user: # 로그인한 사용자라면
all_tweet = TweetModel.objects.all().order_by('-created_at')
return render(request, 'tweet/home.html', {'tweet':all_tweet})
else:
return redirect('/sign-in')
elif request.method == 'POST':
user = request.user
my_tweet = TweetModel()
my_tweet.author = user
my_tweet.content = request.POST.get('my-content', '')
my_tweet.save()
return redirect('/tweet')
all_tweet = TweetModel.objects.all().order_by('-created_at')
타임라인은 최신 글이 상단에 오기 때문에
최신순을 역순으로 정렬되도록 order_by에 -를 붙여줌
return render(request, 'tweet/home.html', {'tweet':all_tweet})
tweet/home.html을 화면에 띄우면서 {'tweet':all_tweet}라는 데이터를 화면에 전달
읽어온 게시글을 화면에 노출시키기
templates/tweet/home.html:
<div class="row">
{% for tw in tweet %}
<div class="col-md-12 mb-2">
<div class="card">
<div class="card-body">
<div class="media">
<div class="media-body">
<h5 class="mt-0">{{ tw.content }}</h5>
</div>
<div style="text-align: right">
<span style="font-size: small">{{ tw.author.username }}-{{ tw.created_at|timesince }} 전</span>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{{ tw.author.username}} : 작성자
{{ tw.content }} : 작성된 내용
{{ tw.created_at|timesince}} : 작성된 시간 (|timesince를 하지 않으면 몇월 몇일 몇시 몇분이라고 나온다)
게시글 삭제하기
tweet/views.py:
from django.contrib.auth.decorators import login_required
@login_required # 로그인 한 사용자만 접근할 수 있게 해주는 기능
def delete_tweet(request, id):
my_tweet = TweetModel.objects.get(id=id)
my_tweet.delete()
return redirect('/tweet')
tweet/urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'), # 127.0.0.1:8000 과 views.py 폴더의 home 함수 연결
path('tweet/', views.tweet, name='tweet') # 127.0.0.1:8000/tweet 과 views.py 폴더의 tweet 함수 연결
path('tweet/delete/<int:id>', views.delete_tweet, name='delete-tweet'),
]
<int:id>의 숫자는 id에 담겨져 delete_tweet에 전달
이 id를 views.py의 delete_tweet(request, id)에서 매개변수로 받아 사용할 수 있는 것
view와 url이 연결되었으므로, 10번 게시물 삭제는 /tweet/delete/10이라 요청하면 된다
templates/tweet/home.html:
{% if tw.author == user %} # 게시글의 author(글쓴이)와 지금 로그인한 사용자가 같으면
<div style="text-align: right">
<a href="/tweet/delete/{{ tw.id }}">
<span class="badge rounded-pill bg-danger">삭제</span>
</a>
</div>
{% endif %}
<div style="text-align: right">
<a href="#">
<span class="badge rounded-pill bg-success">보기</span>
</a>
</div>
- @login_required : 로그인 하지 않으면 접근이 불가능하게 만드는 기능
- user = request.user.is_authenticated : 로그인의 여부만 검증해 주는 기능
- Ctrl + Shift + n : 크롬 시크릿 모드 (로그인 로그아웃 테스트하기 좋음)
- Shift + \ : |
'Django' 카테고리의 다른 글
Django 기초 4주차 2_Sparta Coding Club (0) | 2023.04.05 |
---|---|
ERD 설계, 구축_특강 (6) | 2023.04.05 |
Django 기초 4주차 1_Sparta Coding Club (0) | 2023.04.05 |
Django 기초 2주차_Sparta Coding Club (2) | 2023.04.04 |
Django 기초 1주차_Sparta Coding Club (2) | 2023.04.03 |