1) 파이참 - 장고 파일 생성
2) 재생 버튼 눌러서 장고 서버가 잘 연결되는지 확인
만약 연결된 포트 넘버가 장고에서 이미 사용 중이라는 오류가 난다면, port 8000과 관련된 모든 프로세스를 죽이고 다시 실행시키면 된다
Mac 터미널에서
sudo lsof -t -i tcp:8000 | xargs kill -9" 입력
3) 화면에 글자 띄우기
from django.http import HttpResponse
def base_response(request):
return HttpResponse("안녕하세요! 장고의 시작입니다!")
#HttpResponse() 괄호 안에 있는 내용을 인터넷 창 화면에 보여주는 역할
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('test/', views.base_response,name='first_test'),
]
4) 화면에 내가 만든 html 띄우기
from django.shortcuts import render
#render라는 함수는 template에 있는 html파일을 찾아서 보여준다
def first_view(request):
return render(request, 'my_test.html')
from django.contrib import admin
from django.urls import path
from . import views
urlpatterns = [
path('admin/', admin.site.urls),
path('test/', views.base_response,name='first_test'),
path('first/', views.first_view,name='first_view'),
]
구현하고 싶은 기능
🔰 사용자 관리 (회원가입/로그인/로그아웃)
🔰 글쓰기
1) 앱 생성
user: 사용자 관리 (회원가입/로그인/로그아웃) 담당
tweet: 글 (글쓰기, 삭제, 수정, 댓글) 담당
django-admin startapp user
django-admin startapp tweet
2) 프로젝트 세팅
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tweet',
'user',
]
3) 데이터베이스 연결
우측 데이터베이스 클릭 - Data Source from Path 클릭 - 장고가 생성한 db.sqlite3 선택
4) User Model 만들기
#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)
5) 만든 모델 데이터베이스에 넣기
⭐ 데이터베이스 변경을 알려주는 명령어 makemigrations
python manage.py makemigrations
⭐ 변경된 데이터베이스를 적용시켜주는 migrate
python manage.py migrate
6) Admin 기능
python manage.py createsuperuser
관리자 생성 후 로그인
관리자 홈페이지에서 회원 아이디 삭제 가능
from django.contrib import admin
from .models import UserModel
# Register your models here.
admin.site.register(UserModel) # 이 코드가 나의 UserModel을 Admin에 추가 해 줍니다
위에까지는 user 앱에서 작업한 것 !
아래부터는 tweet 앱 작업
7) tweet 모델 만들기
# 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를 사용해서 넣음
python manage.py makemigrations
python manage.py migrate
from django.contrib import admin
from .models import TweetModel
# Register your models here.
admin.site.register(TweetModel)
사용자 관리와 로그인 화면 띄우기
8) 템플릿 만들기 (HTML 작성하기)
9) url - view - template 이어주기
# 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('user.urls'))
user앱의 urls.py에 연결시키는 코드
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'),
]
10) 사용자 관리와 로그인 - 회원가입 기능 만들기
POST: 값을 주거나 수정, 삭제를 요청할 때 사용
GET: 값을 읽어올 때 사용
# user/views.py
def sign_up_view(request):
if request.method == 'GET': # GET 메서드로 요청이 들어 올 경우
return render(request, 'user/signup.html')
elif request.method == 'POST': # POST 메서드로 요청이 들어 올 경우
return ""
<div class="wrap">
<h2 class="title-center"> 회원가입 </h2>
<form class="form-area" method="post" action="/sign-up/">
{% csrf_token %}
<div class="form-group mt-2 mb-2">
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')
redirect 함수를 이용해서, 저장 완료 되었다면 로그인 페이지 인 /sign-in url로 이동시킨다
11) 사용자 관리와 로그인 - 로그인 기능 만들기
# user/views.py
from django.http import HttpResponse
def sign_in_view(request):
if request.method == 'POST':
return HttpResponse("로그인 성공!")
elif request.method == 'GET':
return render(request, 'user/signin.html')
<!-- 윗부분 생략 -->
<div class="wrap">
<h2 class="title-center"> 로그인</h2>
<form class="form-area" action="/sign-in/" method="post">
{% csrf_token %}
<div class="form-group mt-2 mb-2">
<!-- 아랫 부분 생략 -->
# user/views.py
def sign_in_view(request):
if request.method == 'POST':
username = request.POST.get('username', None)
password = request.POST.get('password', None)
return HttpResponse("로그인 성공!")
elif request.method == 'GET':
return render(request, 'user/signin.html')
🔥 username과 password를 검사하기 위해서는 사용자를 불러와야 한다
# 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 = UserModel.objects.get(username=username) # 사용자 불러오기
if me.password == password: # 저장된 사용자의 패스워드와 입력받은 패스워드 비교
request.session['user'] = me.username # 세션에 사용자 이름 저장
return HttpResponse(me.username)
else:
return redirect('/login')
elif request.method == 'GET':
return render(request, 'user/signin.html')
회원가입 중복 방지
# user/views.py
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:
exist_user = UserModel.objects.filter(username=username)
if exist_user:
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')
12) 장고 사용자 모델 활용하기
from django.db import models
from django.contrib.auth.models import AbstractUser #장고 모델 불러오기
# Create your models here.
class UserModel(AbstractUser):
class Meta:
db_table = "my_user" # 여기는 테이블 이름이에요! 꼭 기억 해 주세요!
bio = models.TextField(max_length=500, blank=True)
#내가 생성했던 사용자 모델 중 남기고 싶은 부분
프로젝트 이름인 폴더(가장 상위 개념)의 setting.py 가장 하단에 아래 코드 추가
# mySpartaSns/settings.py
AUTH_USER_MODEL = 'user.UserModel'
13) User 모델을 데이터베이스에 적용시키기
python manage.py makemigrations
python manage.py migrate
14) 장고의 사용자 모델 적용 - 회원가입 수정하기
# user/views.py
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') # 회원가입이 완료되었으므로 로그인 페이지로 이동
my_user 데이터 테이블을 살펴보면 password 부분은 장고에 의해 자동적으로 암호화 되어 있다
15) 장고의 사용자 모델 적용하기 - 로그인 수정하기
# user/views.py
from django.contrib import auth # 사용자 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("로그인 성공")
else:
return redirect('/sign-in') # 로그인 실패
elif request.method == 'GET':
return render(request, 'user/signin.html')
from django.contrib import auth 를 사용하면 위처럼 비밀번호까지 체크를 해주고, 로그인 기능까지 간단하게 해결이 가능하다
16) 로그인 이후 기능 다듬기 - 로그인 후 페이지 이동하기
template에서 아래와 같이 새로운 폴더 생성 및 페이지 작업
페이지 연결하기
tweet/views.py
# tweet/views.py
from django.shortcuts import render, redirect
# Create your views here.
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
# 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 함수 연결
]
장고 폴더(가장 상위 개념/프로젝트명) urls.py
# 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'))
]
17) 장고 template 수정하기
home.html
<h5 class="card-title">{{ user.username }}</h5>
<p class="card-text"> {{ user.bio }}</p>
base.html
{% if not user.is_authenticated %}
<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>
{% else %}
{{ user.username }} 님 반갑습니다!
{% endif %}
18) 로그인 필요 기능과 로그아웃 만들기
로그인과 관련된 대표적인 기능
📒 로그인한 사람만 페이지에 접근 가능하게 만들기
tweet앱의 views.py를 열어 주시고, 아래의 코드처럼 tweet 함수에 로그인 한 사용자를 판단하는 기능을 추가
# tweet/views.py
from django.shortcuts import render, redirect
def tweet(request):
if request.method == 'GET': # 요청하는 방식이 GET 방식인지 확인하기
user = request.user.is_authenticated # 사용자가 로그인이 되어 있는지 확인하기
if user: # 로그인 한 사용자라면
return render(request, 'tweet/home.html')
else: # 로그인이 되어 있지 않다면
return redirect('/sign-in')
📒 로그인한 사람은 사용 안 해도 되는 페이지
# user/views.py
def sign_up_view(request):
if request.method == 'GET':
user = request.user.is_authenticated # 로그인 된 사용자가 요청하는지 검사
if user: # 로그인이 되어있다면
return redirect('/')
else: # 로그인이 되어있지 않다면
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
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':
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("/")
view 작업 후 url 연결
# user/urls.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')
]
html의 로그아웃 부분을 추가해 주기 위해서 templates 폴더의 base.html 수정
<form class="form-inline my-2 my-lg-0">
{% if not user.is_authenticated %}
<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>
{% else %}
<ul class="navbar-nav mr-auto">
<li class="nav-item" disabled>
<span class="nav-link">
{{ user.username }} 님 반갑습니다!
</span>
</li>
<li class="nav-item">
<a class="nav-link" href="/logout"> 로그아웃 </a>
</li>
</ul>
{% endif %}
19) 게시글 쓰기
# tweet/views.py
from .models import TweetModel # 글쓰기 모델 -> 가장 윗부분에 적어주세요!
def tweet(request):
if request.method == 'GET': # 요청하는 방식이 GET 방식인지 확인하기
user = request.user.is_authenticated # 사용자가 로그인이 되어 있는지 확인하기
if user: # 로그인 한 사용자라면
return render(request, 'tweet/home.html')
else: # 로그인이 되어 있지 않다면
return redirect('/sign-in')
elif request.method == 'POST': # 요청 방식이 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')
20) 게시글 삭제
# 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': # 요청 방식이 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')
→ TweetModel을 created_at의 역순으로 불러오는 코드. 타임라인은 최신 글이 가장 상단에 있기 때문에 생성된 시간의 역순으로 불러옴
return render(request, 'tweet/home.html', {'tweet': all_tweet})
→ tweet/home.html을 화면에 띄우면서 {'tweet':all_tweet} 라는 데이터를 화면에 전달
tweet/home.html 수정
<!-- templates/tweet/home.html -->
<hr>
<!-- 작성 된 글이 나오는 곳 -->
<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>
# 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')
url 연결하기
# tweet/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('tweet/', views.tweet, name='tweet'),
**path('tweet/delete/<int:id>', views.delete_tweet, name='delete-tweet'),** 추가
]
templates/tweet/home.html 수정하기 <- 삭제, 보기 버튼 나오도록