본문 바로가기
BE/Django

Blog 프로젝트의 views.py 작성 후 tests.py 통과까지

by aeyong-dev 2023. 5. 24.

https://github.com/YoonKeumJae/LikeLion/tree/main/BE/HomeWork/week3

 

GitHub - YoonKeumJae/LikeLion: LikeLion

LikeLion. Contribute to YoonKeumJae/LikeLion development by creating an account on GitHub.

github.com

 멋사 BE Django수업의 첫날은 models.py 작성이었습니다. models.py는 어렵지 않게 작성하였지만, 다음 과제인 views.py를 작성하면서 꽤 애먹었어요. 이번 과제의 목표는 views.py에서 post에 대한 CRUD기능을 만들고 tests.py에서 테스트 코드를 작성하는 것이었습니다. 예제 코드가 있었지만 봐도 무슨 말인지 모르겠고, 운영진분이 추천하는 책도 사서 조금 읽었지만 이해가 될 듯 말 듯하고.. chatGPT한테 예제 코드를 물어봐가면서 어떻게든 해내버렸습니다. 

 

 views.py는 MVT패턴의 View를 담당하는 파일입니다. MVT패턴이란 Model이 data를, View가 logic을, T가 Template(사용자에게 보이는 부분)을 담당하는 패턴을 말합니다. 내부 로직을 담당하는 views.py가 핵심적인 부분이라고 할 수 있어요. 사용자에게 요청을 받아서 post에 대한 CRUD의 로직을 만드는 겁니다. 예제 코드의 함수들이 꽤 낯설었지만 천천히 공부하니 생각보다 어렵지 않았습니다. 사실 어려웠어요


def home(request):
    posts = Post.objects.all()
    paginator = Paginator(posts, 10)
    pageNum = request.GET.get("page")
    posts = paginator.get_page(pageNum)
    return render(request, "home.html", {"posts": posts})

 

models.py에서 Post 모델을 생성했죠? posts에 Post객체들을 전부 가져와서 담아줍니다. 

Paginator()를 이용하여 posts를 10개씩 페이지를 나눠줘요. 

GET방식으로 몇 페이지인지 가져와주고요, 

그 page의 포스트들을 posts에 넣어줍니다. 

return 하는데, render() 함수로 home.html을 사용자에게 보여줍니다. 


이런 식으로 한 줄씩 찾아봐가며 코드를 이해해 나갔습니다.

def post_create(request):
    title = request.POST.get("title")
    body = request.POST.get("body")
    date = request.POST.get("date")
    category = Category.objects.get(pk=request.POST.get("category"))
    post = Post.objects.create(title=title, body=body, date=date, category=category)
    return redirect(reverse("post_detail", args=[post.pk]))

post를 생성하는 함수입니다. post를 생성하고 return 해줍니다. 

그런데 render()를 쓰지 않고 redirect()를 썼네요? 

그리고 reverse()와 args=[post.pk]가 무엇인지 잘 모르겠습니다. 


render() vs redirect()

render()는 html파일을 받아서 화면에 띄워주는 역할을 합니다. 템플릿을 불러와요.

반면에 redirect()는 URL로 이동시켜 주는 역할을 합니다. 

urls.py에서 지정한 url로 이동시켜 주고, 그 url에 지정된 view가 실행됩니다.

그러고 나서 render()할지, 다시 redirect()할지 정해지는 거예요.

저는 render()와 redirect()의 차이를 잘 몰라서 조금 헤맸습니다. 

render()는 http status code 200(성공)을 반환합니다. 

redirect()는 http status code 304(redirection)를 반환합니다. 

이것을 잘 염두에 두고 코드를 작성해야 해요.

 

reverse()가 뭐지?

chatGPT에게 물어보니 이렇게 답변하네요.

그러니까, urls.py에서 정한 url의 이름을 넣으면 그 url로 이동한다는 뜻이네요. args로 인수도 전달할 수 있고요. 


 

pk에 대해서

chatGPT야, pk에 대해 알려줘.

레코드를 구분하는 고윳값이 primary key, 즉 pk였군요. 


 

return redirect(reverse("post_detail", args=[post.pk])의 뜻은 결국 

"post_detail이라고 이름 지은 url에 post의 고윳값을 인자로 전송해 줘" 

정도가 되겠습니다. 

 

이런 식으로 update, delete 기능까지 구현하고 tests.py 코드를 작성했어요.

과제에 첨부된 예제 코드를 보다가 이해가 잘 되지 않아 chatGPT에게 테스트 코드 작성을 부탁했습니다. 

그런데 chatGPT도 자꾸 틀리더라고요.

어떤 식으로 접근해야 하는지 감만 잡고 직접 테스트 코드를 작성했습니다.


    def setUp(self):
        # create dummy data
        self.user = User.objects.create_user(username="test", password="test")
        self.blog = Blog.objects.create(blogName="Test Blog", user=self.user)
        self.category = Category.objects.create(
            categoryName="Test Category", blog=self.blog
        )
        self.post = Post.objects.create(
            title="Test Post", body="Test body", category=self.category, date="2020-01-01"
        )

먼저 더미 데이터를 생성했습니다. 

예제 코드에서는 Client를 import 해서 사용하던데, 저는 모델을 작성할 때 User를 import 해서 작성했습니다. 

이 부분에서 자꾸 에러가 생겼어요.

어떻게 할지 고민하다가 결국 self.user는 User객체를 생성했습니다. 

그리고 다른 테스트 함수에서는 client객체를 생성해서 에러를 고쳤습니다. 


 

    def test_post_create(self):
        response = self.client.post(reverse('post_create'), {
            'title': 'New Post',
            'body': 'This is a new post.',
            'date': '2023-05-23',
            'category': 'newCatagory'
        })
        self.assertEqual(response.status_code, 302)  
        self.assertEqual(Post.objects.count(), 2)

처음에는 이렇게 작성했었어요.

자꾸 category에는 Category형식만 들어올 수 있다고 에러가 떴습니다. 

도무지 이해가 안 돼서 멋사 대표님께 여쭤봤습니다. 

대표님과 한참 머리 싸매고 고민하다가 문제점을 찾았어요.

우리가 블로그를 포스팅할 때, 이미 있는 카테고리에 글을 작성하지 카테고리를 생성하지는 않잖아요?

그래서 아래와 같이 코드를 바꿔주었습니다. 

def test_post_create_view(self):
        client = Client()
        data = {"title": "Test Post", "body": "Test body", "category": self.category.pk}
        response = client.post(reverse("post_create"), data)
        self.assertEqual(response.status_code, 302)

이미 있는 카테고리, 즉 self.category의 pk를 넣어주니 정상적으로 테스트를 통과했습니다. 


 

테스트 통과. 야호!

사실 이것들 말고도 많은(아주 많은) 문제들이 있었는데, 기록을 해놓지 않으니 잘 기억이 나지 않네요.

기록을 습관화해서 최대한 많은 것들을 적을 수 있도록 노력하겠습니다. 

그리고 저도 아직 배우는 입장이다 보니 틀린 부분이 있을 수도 있어요(아마 있을 거라 생각해요).

언제든지 댓글로 지적해 주시면 바로 수정하도록 하겠습니다.