[DRF] Issue Report - 게시글 작성 post 실패

Yungsang Hwang·2022년 7월 13일
0

Django-Rest-Framework

목록 보기
7/15

Issue Report - 게시글 작성 post 실패


🕵️‍♀️ 상황

  • API 개발 명세를 작성한 대로 view를 코딩했고, 테스트를 진행하기 위해서 테스트코드 또한 작성한 상태
  • python [manage.py](http://manage.py) test 로 코드가 제대로 작동하는지 테스트 했지만 해결되지 않음ㅋㅋ
  • 1) webmaster.views
    class NoticeView(APIView):
        def post(self, request):
            notice_serializer = NoticeSerializer(data=request.data)
            print(notice_serializer)
            if notice_serializer.is_valid():
                notice_serializer.save()
                return Response({"message": "공지사항 작성에 성공했다북"}, status=status.HTTP_200_OK)
            else:
                print(notice_serializer.errors)
                return Response({"message": "공지사항 작성에 실패했다북"}, status=status.HTTP_400_BAD_REQUEST)
  • 2) webmaster.urls
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('', views.NoticeView.as_view(), name='notice'),
        path('list_notice', views.NoticeListView.as_view(), name='list_notice'),
    ]
  • 3) webmaster.test
    from django.test import TestCase
    from .models import Notice as NoticeModel
    from user.models import User as UserModel
    from rest_framework.test import APITestCase
    from django.urls import reverse
    
    class NoticeTest(APITestCase):
        def setUp(self):
            self.user = UserModel.objects.create_user('admin', '123')
            title = "거뮤니티 ver.1.0 개발노트"
            content = "회원가입, 로그인, 공지사항, 질문 답글 게시판이 추가되었습니다"
    
            self.data = {
                "user" : self.user.id,
                "title" : title,
                "content": content
            }
    
            self.notice = NoticeModel.objects.create(**self.data)
            self.user = NoticeModel.objects.all()
    
        def test_notice(self):
            response = self.client.post(reverse('notice'), self.data)
            print(f'이건 포스트 -> {response.data}')
            self.assertEqual(response.status_code,200)

📜 오류코드

Traceback (most recent call last):
  File "K:\coder_ys\gomunity\webmaster\tests.py", line 20, in setUp
    self.notice = NoticeModel.objects.create(**self.data)
  File "K:\coder_ys\gomunity\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "K:\coder_ys\gomunity\venv\lib\site-packages\django\db\models\query.py", line 512, in create
    obj = self.model(**kwargs)
  File "K:\coder_ys\gomunity\venv\lib\site-packages\django\db\models\base.py", line 541, in __init__
    _setattr(self, field.name, rel_obj)
  File "K:\coder_ys\gomunity\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 235, in __set__
    raise ValueError(
ValueError: Cannot assign "1": "Notice.user" must be a "User" instance.

🎯 트러블슈팅

  1. 로직 재설계

    • simple jwt 토큰이 포함된 API 기능 작동을 유도한다
  2. POSTMAN 테스트

    • POSTMAN에서 성공한 것을 확인하고 테스트코드를 작성한다
  3. test.py 코드 작성

  4. 개념 파악하기

    • API 플로우
      • 로그인 된 사용자가
      • 제목을 입력하고
      • 내용을 입력하고
      • 작성하기 버튼을 누르면
      • 공지사항 데이터베이스에 저장되어야 한다
    • 필요한 것
      • 로그인한 사용자를 확인하기 위한 jwt 토큰
      • 제목, 내용 등의 프론트엔드 입력
  5. 의사코드

    • Request
      • 로그인한 사용자를 받는다 → request.data[’user’] =request.user
      • 제목, 콘텐츠, 이미지를 리퀘스트 받는다
      • 받은 내용을 변수로 저장하기
    • API Progress
      • 리퀘스트 받은 데이터를 NoticeSerializer에 넣는다
      • notice_serializer가 is_valid하다면 save()
    • Response
      • 성공했다면 “공지사항 작성 성공했다북!” 메시지 띄움
      • 실패했다면 “공지사항 작성 실패했다북!” 메시지 띄움
  6. 코딩

class NoticeView(APIView):
	def post(self, request):
		request.data['user'] = request.user 
		notice_serializer = NoticeSerializer(data=request.data)
		if notice_serializer.is_valid():
			notice_serializer.save()
			return Response({"message":"공지사항 작성 성공했다북"} notice_serializer.data, status=status.HTTP_200_OK)
		else:
			return Response({"message":"공지사항 작성 실패했다북"} notice_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

포스트맨 도큐먼테이션

테스트코드 작성

  1. setUpTestData
    • 유저에 대한 데이터 입력
    • 공지글에 대한 데이터 입력
    • create_user로 유저 정보 생성
  2. setUp
    • jwt 토큰
  3. 테스트 내용
    • 공지사항 작성 API url과 셋업 데이터를 연결하여 테스트를 실행
    • client.post 메서드 사용
    • 200번과 일치하는지 assertEqual 작성
class NotionTest(APITestCase):
	@classmethod
	def setUpTestData(cls):
		cls.user_data = {'username':'taein', 'password':'1234'}
		cls.article_data = {'title':'아 어렵다 열받아','content':'힘을내요 슈퍼파월'}
		cls.user = User.objects.create_user('taein', '1234')
	
	def setUp(self):
		self.access_token = self.client.post(reverse('token_obtain_pair'), self.data).data['access']
			
class NoticeTest(APITestCase):
	@classmethod
	def setUpTestData(cls):
		cls.user_data = {'username' : 'heejeong', 'password': '1234'}
		cls.notice_data = {'title' : '안녕' , 'content' : '반갑습니다'}
		cls.user = User.objects.create_user('heejeong', '1234')

	def setUp(self):
		self.acceess_token = self.client.post(reverse('token_obtain_pair'), self.data).data['access']
	
	def test_post_notice(self):
		response = self.client.post(reverse("notice"), cls.notice_data)
		self.assertEqual(response.status_code, 200)

🌸 해결

📌 결론은 simple jwt 토큰이 없는 상태에서 요청을 했기 때문이다!
  • POSTMAN에서 토큰을 담고, request.data에 request.user를 담아서 보냈더니 테스트에 성공했다!
  • 시리얼라이저에서 사용자와 관련된 데이터가 없었기 때문에 시리얼라이저가 is_valid()를 통과하지 못했다.
  • 시리얼라이저의 오류를 알고 싶다면 print(NoticeSerializer().errors)와 같이 errors 메서드로 출력해서 확인해 볼 수 있다
profile
하루종일 몽상가

0개의 댓글