파이썬 장고 실무 기초 3주차 10강
게시글 쓰기
글 작성할 html
게시글 쓰기 - POST 방식
글을 저장할 곳 - tweet 테이블
👉 form 태그에 action과 method를 사용해서 django의 url로 연결
templates/tweet/home.html
<div class="media-body">
<h5 class="mt-0">나의 이야기를 적어주세요</h5>
<p>
<form action = "/tweet/" method = "post">
{% csrf_token %}
<div class="form-group mb-2">
<textarea class="form-control" style="resize: none" name='my-content' id="my-content"></textarea>
</div>
<button type="submit" class="btn btn-primary" style="float:right;">작성하기</button>
</form>
</p>
</div>
csrf token의 자세한 원리가 궁금해서 좀 찾아봤다.
👇👇
POST 요청에 대해서만 csrf token을 발급하고 체크한다.
CsrfViewMiddleware는 MIDDLEWARE 설정에서 기본적으로 활성화 되어있다.
csrf token 발급(사용자가 로그인할 때마다 값이 변경됨)
view가 호출되기 전 csrfmiddlewaretoken 유효성 검증
POST 양식을 사용하는 템플릿에서 <form> 태그 안에 {% csrf_token %} 태그를 사용
동작 과정
사용자가 해당 페이지에 접속하면 Django에서 자동으로 csrf_token을 클라이언트로 보내어 cookie에 저장
사용자가 form을 모두 입력한 후 제출버튼을 클릭한다.
form과 cookie의 csrf_token을 함께 POST로 전송한다.
전송된 token의 유효성을 검증
유효한 요청이면 요청을 처리
token이 유효하지 않거나(없거나 값이 잘못된 경우) 검증 오류 시에는 403 Forbidden Response 반환
https://chagokx2.tistory.com/49
글 저장할 view
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')
로그인 여부에 따라 화면을 다르게 했기 떄문에 현재(로그인 상태) http://127.0.0.1:8000/로 접속해도 자동으로 http://127.0.0.1:8000/tweet 으로 이동한다.
게시글을 불러오는 코드에서 아직 그 화면만 구현했기 때문에 글 쓰기는 가능하지만 쓴 글 읽는 것은 안 된다.
게시글 읽기/삭제
1. 게시글 읽어오기
읽어오기 - GET
tweet > view.py
이 부분이 로그인 상태에서 화면을 보여주는 코드이므로 여기서 글을 불러오도록 한다.
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': all_tweet}는 render() 함수가 템플릿에서 사용할 변수 이름과 값을 지정하는 역할을 한다. all_tweet 쿼리셋은 tweet 변수로 전달되어, home.html 템플릿에서 트윗 목록을 출력할 수 있도록 한다.
👇 더 자세한 설명 👇
{'tweet': all_tweet}은 render() 함수의 세 번째 매개변수로 전달되는 컨텍스트 변수이다. 컨텍스트 변수는 템플릿에서 사용되는 변수를 지정하는 데 사용된다.
{'tweet': all_tweet}에서 tweet은 변수 이름이며, all_tweet은 해당 변수가 가지는 값이다. 이것은 TweetModel 모델에서 조회한 모든 트윗 정보가 포함된 쿼리셋(QuerySet) 객체입니다.
템플릿에서는 {{ tweet }}를 사용하여 이 변수를 참조할 수 있다. 뒤의 글 조회에서 home.html 템플릿에 {% for tw in 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': # 요청 방식이 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')
2. 읽어온 게시글 화면에 노출시키기
return render(request, 'tweet/home.html', {'tweet': all_tweet})
읽어온 게시물을 tweet/home.html로 전달 👉 html에서 이 데이터를 어떻게 다를 것인가?
templates > tweet > home.html
저 부분을 데이터베이스에 저장된 글을 불러오는 함수로 바꾸면 된다.
- python의 for문과 비슷한 형태의 for문이 있어요!
- views.py에서 넘겨 준 TweetModel이 '리스트'로 전달 되기 때문에 반복문을 사용해서 출력 해 줄 수 있어요!
- 각 리스트 하나의 요소는 글쓰기 모델 하나이고, 그 안에 포함된 content, author, created_at 등의 요소들을 뽑아 줄 수 있어요.
잘 나온당!
3. 글 삭제하기
글의 고유 id를 이용해 지울 게시글 판단
삭제 url 👉 http://127.0.0.1:8000/tweet/delete/게시글의id
조건 👉 로그인, 내가 쓴 게시글만 삭제
1) 게시글 삭제 view 만들기
로그인 조건 👉 login_required
# 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')
2) 게시글 삭제 url 만들기
delete_tweet(request,id) 함수에서 id를 매개변수로 받았으므로 주소에서도 변수로 받아 쓸 수 있다 👉 <int:id>
3) 게시글 삭제 url 넣어주기
templates > tweet > home.html
{% if tw.author == user %} 👉 이 게시글의 author (글쓴이) 와, 로그인 한 사용자가 같을 때에만 '삭제' 버튼
댓글
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)
class TweetComment(models.Model):
class Meta:
db_table = "comment"
tweet = models.ForeignKey(TweetModel, on_delete=models.CASCADE)
author = models.ForeignKey(UserModel, on_delete=models.CASCADE)
comment = models.CharField(max_length=256)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
python manage.py makemigrations
python manage.py migrate
tweet/views.py
# 상세보기
@login_required
def detail_tweet(request, id):
my_tweet = TweetModel.objects.get(id=id)
tweet_comment = TweetComment.objects.filter(tweet_id=id).order_by('-created_at')
return render(request,'tweet/tweet_detail.html',{'tweet':my_tweet,'comment':tweet_comment})
# 댓글 작성
@login_required
def write_comment(request, id):
if request.method == 'POST':
comment = request.POST.get("comment","")
current_tweet = TweetModel.objects.get(id=id)
TC = TweetComment()
TC.comment = comment
TC.author = request.user
TC.tweet = current_tweet
TC.save()
return redirect('/tweet/'+str(id))
# 댓글 삭제
@login_required
def delete_comment(request, id):
comment = TweetComment.objects.get(id=id)
current_tweet = comment.tweet.id
comment.delete()
return redirect('/tweet/'+str(current_tweet))
# 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'),
path('tweet/<int:id>', views.detail_tweet, name='detail-tweet'),
path('tweet/comment/<int:id>', views.write_comment, name='write-comment'),
path('tweet/comment/delete/<int:id>', views.delete_comment, name='delete-comment'),
]
templates/tweet/tweet_detail.html 추가
-완성
파이썬 장고 실무 기초 4주차
Many - To - Many : 팔로우 - 팔로워 추가하기
팔로우-팔로워 모델은 many-to-many 모델입니다. 팔로우-팔로잉 모델은 '사람' 간의 모델이기 때문에 데이터베이스 모델을 하나 더 생성하지 않고, ManyToMany 모델에 장고의 user들을 넣어줄게요!
UserModel에 Follower 추가하기
사용자와 연관되어 있으므로 user 앱에서 진행
UserModel Migrate하기
python manage.py makemigrations
python manage.py migrate
팔로우 리스트 만들기
이번에도 역시 view 만들기(views.py) >> url 이어주기(urls.py) >> html 파일 넣기
GitHub 댓글