$ django-admin startapp user
$ django-admin startapp tweet
settings.py에 앱생성후 생성한 앱을 추가해 준다.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
**'tweet',**
**'user',**
]
ORM (Object Relational Mapping) 은 데이터베이스를 하나의 '객체(Object)' 덩어리로 보고, 데이터베이스를 SQL언어가 아닌 클래스로 쉽게 표현 및 사용 할 수 있게 해 줍니다.
class myBakery:
bread_type = '' # 빵의 종류
bake_time = '' # 굽는 시간
price = 0 # 가격
위와 같은 클래스를 데이터베이스의 형태로 만들어서 사용 하려고 합니다
클래스 이름과 내부에 선언 된 변수들이 '비슷한 성격'들을 가지고 있죠~? 우리가 ORM 모델을 만들 때에도 마찬가지로 어떤 역할을 하는 모델을 생성 할 것인지, 어떤 요소들을 담을것인지 고민이 필요합니다!
직접 만들어 보면서 적용 해 볼까요~?
Django는 기본적으로 User모델을 제공합니다. 사용자의 관리와 로그인/로그아웃이 이미 다 구현이 되어있어요! 하지만 우리가 직접 먼저 만들어본 후에 Django에서 제공하는 모듈을 사용하려고 합니다!
django의 user앱 아래의 models.py에 작성 해 볼게요!
#user/models.py
from django.db import models
# Create your models here.
class UserModel(models.Model):
class Meta:
db_table = "my_user"
username = models.CharField(max_length=20, null=False)
password = models.CharField(max_length=256, null=False)
bio = models.CharField(max_length=256, default='')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
위의 모델 클래스에서 class Meta 는 이 모델의 정보를 담고있습니다. 여기에서는 테이블 이름만 정해주었습니다
그리고 django에서 제공하는 models를 사용해서 각 요소에 어떤 데이터의 형식이 들어갈 지 정해주고, 각 필드에 제한을 두었어요.
방금 우리가 열심히 만든 User Model을 데이터베이스에 넣어주려고 합니다! 두 단계로 나눌 수 있어요. '데이터베이스 변경을 알려주는 명령어'
와 '변경된 데이터베이스를 반영 해 주는 명령어'
로 나누어집니다.
python manage.py makemigrations
python manage.py migrate
user.0001_initial
이라고 보이네요! 이게 우리가 user앱에서 만든 모델이 적용되었다는 얘기입니다!
장고는 우리가 코드를 많이 작성하지 않고도 사용 할 수 있도록 이미 많은 기능이 구축되어 있습니다.
대표적인 예가 바로 'Admin'이에요.
장고 서버를 실행시켜주고, http://127.0.0.1:8000/admin 으로 접속 해 주세요
python manage.py createsuperuser
그리고 아까 우리가 만들어준 UserModel을 넣어 주려고 해요! 다음과 같이 코드를 입력 해 주세요!
아래의 코드를 user의 admin.py에 붙여넣어 주세요
from django.contrib import admin
from .models import UserModel
# Register your models here.
admin.site.register(UserModel) # 이 코드가 나의 UserModel을 Admin에 추가 해 줍니다
이제 다시 장고 Admin 페이지로 가서 새로고침을 해 주면 UserModel이 들어가 있는 것을 볼 수 있어요!
SNS 게시글은 작성자, 내용, 글 생성일자, 수정일자 정도 있으면 좋을 것 같아요!
tweet앱의 models.py로 들어가서, 아래의 코드를 넣어주세요.
# tweet/models.py
from django.db import models
from user.models import UserModel
# Create your models here.
class TweetModel(models.Model):
class Meta:
db_table = "tweet"
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
content = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
아까와는 조금 다른 부분이 눈에 띄네요! ForeignKey는 '외부 모델을 가져와서 사용하겠다.' 라는 얘기에요.
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
author는 새로운 사람이 아니라, 아까 우리가 만들어 주었던 User Model의 사용자가 작성 한 글 이기 때문에 ForeignKey를 사용해서 넣어주었습니다.
마찬가지로 데이터베이스 마이그레이션 마이그레이트 해주고, admin안에 db도 넣어 주세요!
우선 우리의 프로젝트 탐색기에서, templates 폴더 아래에 다음과 같이 파일들을 만들어주세요!
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %} | spartaSNS</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js"
integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf"
crossorigin="anonymous"></script>
<style>
.title-center {
text-align: center;
margin-top: 50px;
}
.wrap {
width: 400px;
margin: 0 auto;
}
.form-area {
margin-top: 25px;
}
.timeline-container {
margin-top : 25px
}
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="/">SpartaSNS</a>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#"> 친구 <span class="sr-only"></span></a>
</li>
</ul>
</div>
<form class="form-inline my-2 my-lg-0">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="/sign-in"> Sign In <span class="sr-only"></span></a>
</li>
<li class="nav-item active">
<a class="nav-link" href="/sign-up"> Sign Up <span class="sr-only"></span></a>
</li>
</ul>
</form>
</div>
</nav>
{% block content %}
{% endblock %}
</body>
</html>
signup.html
{% extends 'base.html' %}
{% block title %}
회원가입
{% endblock %}
{% block content %}
<div class="container">
<div class="wrap">
<h2 class="title-center"> 회원가입 </h2>
<form class="form-area">
<div class="form-group mt-2 mb-2">
<label for="username">이름</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group mt-2 mb-2">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<div class="form-group mt-2 mb-2">
<label for="password2">비밀번호 확인</label>
<input type="password" class="form-control" id="password2" name="password2">
</div>
<div class="form-group mt-2 mb-2">
<label for="bio">나를 한마디로</label>
<input type="text" class="form-control" id="bio" name="bio">
</div>
<hr>
<div style="float: right">
<button type="submit" class="btn btn-primary">회원가입</button>
<a href="/sign-in" class="btn btn-secondary">로그인 페이지로</a>
</div>
</form>
</div>
</div>
{% endblock %}
signin.html
{% extends 'base.html' %}
{% block title %}
로그인
{% endblock %}
{% block content %}
<div class="container">
<div class="wrap">
<h2 class="title-center"> 로그인</h2>
<form class="form-area">
<div class="form-group mt-2 mb-2">
<label for="username">이름</label>
<input type="text" class="form-control" id="username" name="username">
</div>
<div class="form-group mt-2 mb-2">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password">
</div>
<hr>
<div style="float: right">
<button type="submit" class="btn btn-primary">로그인</button>
<a href="/sign-up" class="btn btn-secondary">회원가입 페이지로</a>
</div>
</form>
</div>
</div>
{% endblock %}
# mySpartaSns/urls.py
from django.contrib import admin
from django.urls import path, **include**
urlpatterns = [
path('admin/', admin.site.urls),
**path('', include('user.urls'))**
]
from django.shortcuts import render
# Create your views here.
def sign_up_view(request):
return render(request, 'user/signup.html')
def sign_in_view(request):
return render(request, 'user/signin.html')
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'),
]
from django.shortcuts import render, **redirect
from .models import UserModel**
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:
new_user = UserModel()
new_user.username = username
new_user.password = password
new_user.bio = bio
new_user.save()
return redirect('/sign-in')**
html의 input에 입력 했던 친구들은 각각 username, password, password2, bio로 sign_up_view()함수로 들어가게 됩니다!
html에서 넘겨준 데이터를 views.py에서 받아줍니다.
password와 password2가 일치하는지 확인 해 주고, 일치하면 저장 해 줍니다.
user앱의 views.py의 sign_up_view함수에 아래와 같이 추가 해 주겠습니다.
redirect 함수를 이용해서, 저장 완료 되었다면 로그인 페이지 인 /sign-in url로 이동 하게 해 줍니다.
def sign_in_view(request):
if request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
me = UserModel.objects.get(username=username) # 사용자 불러오기
if me.password == password: # 저장된 사용자의 패스워드와 입력받은 패스워드 비교
request.session['user'] = me.username # 세션에 사용자 이름 저장
return HttpResponse("로그인 성공!")
else: # 로그인이 실패하면 다시 로그인 페이지를 보여주기
return redirect('/sign-in')
elif request.method == 'GET':
return render(request, 'user/signin.html')
username, password가 /sign-in으로 전달 되기 때문에, 'sign_in_view'함수가 실행이 됩니다.
user앱의 sign_in_view 함수에 로그인 기능들을 추가 해 볼게요~! 위에서 말했던 '세션'기능을 사용하려고 해요!
username과 password를 검사 하기 위해서는 '사용자'를 불러와야합니다.
UserModel을 사용해서 사용자를 불러오는 작업을 해 볼게요!