[TIL / Django] Westagram - 게시물 등록, 표출

haejun-kim·2020년 8월 6일
2

[Django]

목록 보기
15/20
post-thumbnail

Post App 생성

현재 생성한 User 라는 앱은 게시글을 등록하는 것과는 기능이 다르다. 보통 앱을 구분하는것은 기능별로 구분하기 때문에 Post라는 새로운 앱을 생성했다.

앱을 새로 생성하면 settings.py 에서 생성한 앱을 등록시키는 절차를 잊지 말자! ( + URL 경로 추가도 )

Model

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에 대한 정보만 가져올 수 있도록 이름을 지정해주는 역할을 한다.

모델을 수정하고 나면 makemigrationmigrate 작업을 잊지 말자

View

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

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 코드를 반환시킨다.

PostDisplayView

해당 클래스는 게시글을 등록하면 그 내용을 볼 수 있는 GET 방식의 통신을 하는 클래스이다. 게시글에 대한 values를 받아와서 list 형태로 출력해주도록 하였다.

Westagram/url

from django.urls import(
    path, 
    include
)

urlpatterns = [
    path('user/', include('User.urls')),
    path('post/', include('Post.urls')),
]

Post 앱을 생성했기 때문에 위와 같이 경로를 설정해준다.

Post/url

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)

파이썬을 파이썬답게 쓰도록 노력하기

0개의 댓글