
현재 생성한 User 라는 앱은 게시글을 등록하는 것과는 기능이 다르다. 보통 앱을 구분하는것은 기능별로 구분하기 때문에 Post라는 새로운 앱을 생성했다.
앱을 새로 생성하면 settings.py 에서 생성한 앱을 등록시키는 절차를 잊지 말자! ( + URL 경로 추가도 )
from django.db import models
from User.models import User
class Post(models.Model):
email = models.ForeignKey(User, on_delete = models.CASCADE)
content = models.TextField(max_length = 300)
image_url = models.URLField()
created_at = models.DateTimeField(auto_now_add = True)
class Meta:
db_table = "posts"
def __str__(self):
return self.email
Post와 관련된 모델들을 정의했다. User 에서 회원가입할 때 이메일을 받았기 때문에, 회원을 구분할 기준이 이메일밖에 없어서 이메일로 정의했고, 게시물의 내용을 저장 할 content , 게시글에 이미지를 올렸을 때 해당 이미지의 URI을 받기위한 image_url, 게시글이 작성 된 날짜와 시간을 표시 해 주기 위해서 created_at을 생성해주었다.
class Meta 부분은 모델을 생성하거나 수정하고나면 migration 작업을 진행해주어야 하는데, migration 작업을 하면 db 테이블이 생성된다. 이 때 생성 될 table의 이름을 지정해주는 역할이다. 만약 이렇게 이름을 지정해주지 않으면 테이블 이름이 App이름_Class이름 으로 django에서 알아서 저장해주기 때문에 굳이 이름을 설정해주고 싶지 않으면 이 부분은 생략해도 좋다.
__str__ 부분은 db 테이블에서 하나의 정보를 가져오고 싶으면 해당 row를 전부 가져오게 되는데 그렇게 되면 메모리 낭비가 생기므로, 내가 email이란 정보만 가져오고싶다면 email에 대한 정보만 가져올 수 있도록 이름을 지정해주는 역할을 한다.
모델을 수정하고 나면 makemigration 과 migrate 작업을 잊지 말자
import json
from django.views import View
from django.http import JsonResponse
from User.models import User
from .models import Post
class PostView(View):
def post(self, request):
data = json.loads(request.body)
try:
if User.objects.filter(id = data['user_id']).exists():
user = User.objects.get(id = data['user_id'])
Post(
user = user,
content = data['content'],
image_url = data['image_url'],
).save()
return JsonResponse({'message' : 'SUCCESS'}, status = 200)
else:
return JsonResponse({'message' : 'UNAUTHORIZED'}, status = 401)
except Exception as e:
return JsonResponse({'message' : f'{e}'}, status = 400)
class PostDisplayView(View):
def get(self, request):
post_data = Post.objects.values()
return JsonResponse({'post_data' : list(post_data)}, status = 200)
게시물을 등록해줄 수 있는 PostView 클래스와 등록한 게시글을 볼 수 있는 PostDisplayView 클래스로 두가지의 클래스를 만들었다.
PostView 클래스에서는 models에서 email에 지정한 ForeignKey를 사용해서 서로 연결시켜주었다. id값에 user_id값을 넣어주었고, 이 id값으로 게시글을 등록한 유저를 찾아내는 역할을 한다.
django에서는 Primary Key를 임의로 지정해주지 않으면 default로 Foreign Key와 Primary Key를 동일하게 설정해준다. 따라서 위 코드에서 primary key에 대한 설정을 따로 해주지 않았기 때문에 foreign key와 primay key는 동일한 id값을 참조한다. 그래서 위와 같은 코드가 정상 동작을 한다.
회원가입을 한 유저의 id값을 받아서 해당 id 가 db에 정상적으로 저장되어 있으면 게시글을 작성했을 때, SUCCESS 메시지를 반환해주고, 회원가입 정보가 없는 유저가 게시글을 등록하려고 하면 권한이 없다는 뜻에 UNAUTHORIZED 라는 문구와 함께 401 코드를 반환해주도록 했다. 그 외의 에러가 발생했을 경우는 해당 에러 자체 이름을 그대로 출력해주며 400 코드를 반환시킨다.
해당 클래스는 게시글을 등록하면 그 내용을 볼 수 있는 GET 방식의 통신을 하는 클래스이다. 게시글에 대한 values를 받아와서 list 형태로 출력해주도록 하였다.
from django.urls import(
path,
include
)
urlpatterns = [
path('user/', include('User.urls')),
path('post/', include('Post.urls')),
]
Post 앱을 생성했기 때문에 위와 같이 경로를 설정해준다.
from django.urls import path
from .views import (
PostView,
PostDisplayView
)
urlpatterns = [
path('post', PostView.as_view()),
path('postdisplay', PostDisplayView.as_view()),
]
두개의 클래스를 만들었기 때문에 각각의 클래스를 호출하기 위해 경로를 구분지어 위와 같이 작성했다.
해당 코드는 위 if조건문이 만족하지 않아 200이 return 되지 않는다면 바로 도달 하는 코드입니다. 따라서 else가 없어도 됩니다. 꼭 있어야 하는 else가 아니라면 적지 않는 것을 추천드립니다.
try:
if User.objects.filter(id = data['user_id']).exists():
user = User.objects.get(id = data['user_id'])
Post(
user = user,
content = data['content'],
image_url = data['image_url'],
).save()
return JsonResponse({'message' : 'SUCCESS'}, status = 200)
else:
return JsonResponse({'message' : 'UNAUTHORIZED'}, status = 401)
파이썬을 파이썬답게 만들기 위한 습관을 기르고 있는 중이다. if 조건을 만족하지 못하면 else:를 해주지 않아도 return문이 동작하기 때문에 꼭 필요한 else가 아니라면 쓰지 않는것이 조금 더 파이썬을 파이썬답게 쓰는 방법이라고 한다.
리뷰를 받은것은 아니였지만 코드를 수정하다보니 내가 models에서는 email로 모델링을 했는데, views에서는 user로 구분하고 있는게 맞지 않다고 생각이 들어 email로 수정을 해주었다.
try:
if User.objects.filter(id = data['user_id']).exists():
email = User.objects.get(id = data['user_id'])
Post(
email = email,
content = data['content'],
image_url = data['image_url'],
).save()
return JsonResponse({'message' : 'SUCCESS'}, status = 200)
return JsonResponse({'message' : 'UNAUTHORIZED'}, status = 401)
파이썬을 파이썬답게 쓰도록 노력하기