요모조모 ʚɞ

[D.R.F] 게시판 기능(CRUD) 구현하기 - 작성일, 작성자 추가 본문

개발/Django RESTful API

[D.R.F] 게시판 기능(CRUD) 구현하기 - 작성일, 작성자 추가

Angela_OH 2021. 2. 20. 04:00

 

안녕하세요 :D

오늘은 지난번까지 실습한 ViewSets과 Custom user를 사용하여 게시판 기능을 구현해보도록 하겠습니다.

 

● ViewSets으로 CRUD 구현하기

 

[D.R.F] 커스텀 유저 구현하기 - 회원가입, 로그인

안녕하세요 (._. )> 오늘은 Django RESTful API로 회원정보를 관리(회원가입/로그인) 해보도록 하겠습니다. Django에서는 기본적으로 사용자 모델인 User 모델을 제공하고 있습니다. 하지만 임의로 원하는

wisdom-990629.tistory.com

 

Custom User 구현하기

 

[D.R.F] ViewSets으로 CRUD 구현하기

안녕하세요  ๑(•‿•)๑ 오늘은 CRUD 구현의 마지막 방식인 ViewSet을 사용해보도록 하겠습니다. APIView에서부터 Mixins, 그리고 Generic CBV를 거쳐 ViewSet까지 왔네요 ㅎㅎ ViewSet은 상속을 여러 번 거

wisdom-990629.tistory.com

 

ViewSets 실습에서는 title과 body field로 Blog 모델을 만들었는데, 사실 이 외에도 다양한 field가 필요합니다!

따라서 게시판의 글을 쓸 때 필요한 field부터 생각해보았습니다.

1. 게시글의 id 값

2. 제목

3. 작성일

4. 작성자

5. 본문

 

models.py

이를 바탕으로 model을 다시 작성해주었습니다.

from django.db import models
from django.conf import settings
from account.models import User

class Blog(models.Model):
    # 1. 게시글의 id 값
    id = models.AutoField(primary_key=True, null=False, blank=False) 
    # 2. 제목
    title = models.CharField(max_length=100)
    # 3. 작성일
    created_at = models.DateTimeField(auto_now_add=True)
    # 4. 작성자
    user = models.ForeignKey(User, null=True, blank=True, on_delete=models.CASCADE)
    # 5. 본문
    body = models.TextField()

id의 경우에는 글 작성 시 id 값을 자동으로 부여해주기 위해 AutoField를 사용하였습니다.

해당 id 값은 각 게시글을 구별하는 역할을 하기 때문에 primary key, 즉 기본키로 설정하였습니다.

다음으로 created_at은 글을 작성한 시간을 의미하며 장고에서 기본적으로 제공하고 있는 DateTimeField를 사용하였고,

작성 시점을 자동으로 저장하기 위해 auto_now_addTrue로 설정해주었습니다.

마지막으로 user는 현재 존재하고 있는 User 객체를 가리키기 위해 Foreign Key(외래키)로 구성하였습니다.

만약 특정 글을 작성한 사용자 정보가 삭제된다면 게시글도 함께 삭제되도록 하기 위해,

on_deleteCASCADE로 설정해주었습니다.

(만약 그게 싫다면 on_delete를 SET_NULL 등으로 설정할 수 있습니다!)

이 외의 titlebody는 이전과 동일하게 설정해주었습니다.

 

모델을 새롭게 정의했기 때문에 마이그레이션을 다시 진행하여야 합니다.

python manage.py makemigrations
python manage.py migrate

참고로, 저의 경우에는 이전에 만들어둔 Blog 모델에 field를 더 추가했기 때문에 여러 오류가 발생하였습니다.

따라서 아래와 같은 명령어를 실행하여 오류를 해결하였습니다.

python manage.py migrate {app 이름} zero
python manage.py migrate {app 이름}

 

다음으로는 views.py를 수정해보도록 하겠습니다.

views.py 
from .models import Blog
from .serializers import BlogSerializer
from rest_framework import viewsets

# Blog의 목록, detail 보여주기, 수정하기, 삭제하기 모두 가능
class BlogViewSet(viewsets.ModelViewSet):
    queryset = Blog.objects.all()
    serializer_class = BlogSerializer
   
   	# serializer.save() 재정의
    def perform_create(self, serializer):
        serializer.save(user = self.request.user)

저는 BlogSerializer의 user field에 현재 user 값을 전달해주기 위해 perform_create 메소드를 추가해주었습니다.

ViewSets에서 perform_create 메소드를 사용하게 되면 기존의 create 함수를 재정의할 수 있습니다.

즉 기존에 serializer.save()로 실행되었을 코드를 serializer.save(user=self.request.user)로 변경해준 것이죠!

 

serializer.py
from .models import Blog
from rest_framework import serializers

class BlogSerializer(serializers.ModelSerializer):
    user = serializers.ReadOnlyField(source = 'user.nickname')
    class Meta:
        model = Blog
        fields = ['id', 'title', 'created_at', 'user', 'body']

serializer에서 유의해야할 점은 이전에 views.py의 perform_create 메소드에서 user 값을 넘겨주었기 때문에,

serializer에서 해당 값을 받아와야 한다는 것입니다!

저는 ReadOnlyField를 사용하였고 views.py에서 넘겨준 user의 nickname 값을 받아오기 위해,

source='user.nickname'으로 설정해주었습니다.

 

urls.py
from django.urls import path, include
from .views import BlogViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('blog', BlogViewSet)

urlpatterns =[
    path('', include(router.urls))
]

urls.py는 이전과 동일하게 작성해주었습니다.

 

작성한 코드를 바탕으로 서버를 실행시켜 보도록 하겠습니다.

python manage.py runserver

 

127.0.0.1:8000/blog/

 

처음에 서버에 접속하게 되면 위의 사진과 같은 화면을 볼 수 있습니다.

여기서 아래의 게시판 양식에 글을 작성하고 POST 버튼을 누르면 다음과 같은 에러가 발생하게 됩니다!

Cannot assign "<django.contrib.auth.models.AnonymousUser object at 0x000002E05CBD18E0>": "Blog.user" must be a "User" instance.

 

에러 발생!

 

이것은 코드를 작성할 때 serializer에 글을 작성한 작성자 정보(user)를 추가해주었는데,

현재는 로그인이 되지 않은 상태이기 때문에 user 정보가 없어서 발생한 오류입니다!

이에 대한 내용은 다음에 Authentication과 Permission을 익힌 다음 적용해보겠습니다.

현재는 우선 로그인을 해줌으로써 해당 오류를 넘어가보도록(?) 합시다!

django rest framework의 로그인 기능을 활용하기 위해서는 urls.py에 아래의 코드를 추가해주세요.

from django.urls import path, include
from rest_framework import urls

urlpatterns =[
	...
    path('api-auth/', include('rest_framework.urls')),
]

 

이후 다시 게시글을 작성해보면 아래와 같이 우리가 만들어준 field가 모두 정상적으로 출력되는 것을 확인할 수 있습니다.

저는 Blog 객체의 생성과 삭제를 반복하여 id 값이 8이지만, 원래는 1부터 나오는 것이 정상입니다^^..

 

127.0.0.1:8000/blog/

 

이외에도 게시글 전체 목록 보기, 특정 게시글 보기, 수정, 삭제 기능을 모두 활용할 수 있습니다!

 

오늘은 게시글과 관련된 API를 만들어보았습니다!

다음 시간에는 자신의 게시글만 수정/삭제하기 + 오늘 발생한 오류 제거하는 실습을 진행하도록 하겠습니다:D

 

Comments