본문 바로가기
DEV/Web 개발

Web 개발 :: 파이썬 Django Rest Framework(3) _ 클래스형 뷰, 프론트엔드에 출력하기

by 올커 2022. 10. 27.

DRF(Django Rest Framework)(3) _ 클래스형 뷰(Class based View), 프론트엔드 출력하기

01. 클래스형 뷰(Class based view)

  (※ 공식 문서 참고 링크)

 - 클래스형 뷰로 변경했을 때에는 다른 클래스를 상속받을 수 있는 장점 등이 생긴다.

 - 공식문서에 class view 기본 템플릿이 잘 나와있기 때문에 복사하여 일부만 수정하여 사용해도 괜찮다.

 

 - 기존의 article_API view를 아래와 같이 클래스형 뷰로 변경한다.

# articles/views.py

...

class ArticleList(APIView):
    def get(self, request, format=None):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = ArticleSerializer(data = request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

 - 클래스형 뷰를 사용하기 때문에 urls.py도 아래와 같이 변경해주어야 한다.

   클래스형 뷰르 사용할 때에는 클래스뷰 이름 뒤에 .as_view()를 붙여주어야 한다.

from django.urls import path
from articles import views

urlpatterns = [
    path('', views.ArticleList.as_view(), name='index'),
    path('<int:article_id>/', views.article_detail_API, name='article_view'),
]

 - 기존의 article_detail_API view도 마찬가지로 아래와 같이 클래스형 뷰로 변경한다.

# articles/views.py

class ArticleDetail(APIView):
    def get(self, request, article_id, format=None):
        article = get_object_or_404(Article,id=article_id)      # 없는 값을 요청할 경우 404에러 발생
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    def put(self, request, article_id, format=None):
        article = get_object_or_404(Article,id=article_id)
        serializer = ArticleSerializer(article, data=request.data)      # (기존 데이터, 변경할 데이터)
        if serializer.is_valid():
            serializer.save()
            return Response (serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, article_id, format=None):
        article = get_object_or_404(Article,id=article_id)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 - 마찬가지로 urls.py에서 해당되는 view의 url을 다시 지정해준다.

from django.urls import path
from articles import views

urlpatterns = [
    path('', views.ArticleList.as_view(), name='index'),
    path('<int:article_id>/', views.ArticleDetail.as_view(), name='article_view'),
]

02. Swagger 코드 보완

 - post 함수에서 아래와 같이 swagger 데코레이션을 활용하여 swagger에서 API를 확인할 때 자세한 명세를 표기함과 동시에 API를 수정할 수 있도록 만든다.

 

# articles/views.py

from drf_yasg.utils import swagger_auto_schema

...
    @swagger_auto_schema(request_body = ArticleSerializer)      # swagger에 자세한 명세를 표기
    def post(self, request, format=None):
        serializer = ArticleSerializer(data = request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

03. FrontEnd(html)에 출력하기

 - Javascript에서 자체적으로 제공하는 Fetch API 사용하기 (※ 참고 링크)

 - 프론트엔드 작업을 위한 별도의 폴더를 하나 더 생성하고 index.html, index.js 파일을 추가한다.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frontend</title>
    <script src="index.js"></script>        <!-- 자바스크립트 불러오기 -->
</head>
<body>
    <h1>프론트엔드</h1>
    <p>수정을 좀 하고</p>
</body>
</html>
console.log("자바스크립트를 불러왔습니다.")


// 로딩이 되자마자 동작할 것 : window.onload
// async function : 로드를 준비하는 동안 다른 동작을 보여준다.
window.onload = async function loadArticles(){
    const response = await fetch('http://127.0.0.1:8000/articles/', {method:"GET"})

    response_json = await response.json()

    console.log(response_json)

}

 - 이를 작성하고 템플릿을 실행해보면 아래와 같이 *CORS 오류메시지를 확인할 수 있다.

   header를 살펴보면 cross-origin 정책이 'same-origin'이기 때문에 발생한 오류이다.

   frontend : localhost:5500     / backend : 127.0.0.1:8000

*CORS : Origin(주소와 포트)이 다를 경우 보안을 위해 Access 허용을 받도록 하는 것

 - 장고 App의 Header에 CORS에 대한 정보를 추가하여 어떻게 허용할지 설정한다. (※ 참고 링크)

 - 먼저 아래와 같이 명령어를 실행하여 설치한다.

pip install django-cors-headers

 - settings.py의 INSTALLED_APPS에 아래와 같이 추가한다.

INSTALLED_APPS = [
    ...,
    "corsheaders",
    ...,
]

 - settings.py의 MIDDLEWARE에도 아래를 추가한다. 여기서! 아래 코드의 윗부분 "corsheaders.middleware.CorsMiddleware"만 추가하는 것이며, 순서를 꼭 유의하여야 한다.

MIDDLEWARE = [
    ...,
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...,
]

 - 마지막으로 Configuration을 위해 아래 코드도 settings.py 마지막줄에 추가해준다.

CORS_ALLOW_ALL_ORIGINS = True

 - 콘솔 창을 확인해보면 오류가 나타나지 않고 index.js가 실행되어 입력했던 데이터가 있음을 확인할 수 있다.

 - 이제 코드를 화면에 그려보는 코드를 입력해본다.

 - 먼저 html 파일에는 받아오는 데이터를 출력할 div를 아래와 같이 추가한다.

<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Frontend</title>
    <script src="index.js"></script>        <!-- 자바스크립트 불러오기 -->
</head>
<body>
    <h1>프론트엔드</h1>
    <p>수정을 좀 하고</p>
    <div id="articles">           <!-- 새로 받아온 데이터를 저장할 div -->
        
    </div>
</body>
</html>

 - index.js는 아래와 같이 코드를 추가한다.

// index.js

console.log("자바스크립트를 불러왔습니다.")


// 로딩이 되자마자 동작할 것 : window.onload
// async function : 로드를 준비하는 동안 다른 동작을 보여준다.
window.onload = async function loadArticles(){
    const response = await fetch('http://127.0.0.1:8000/articles/', {method:"GET"})

    response_json = await response.json()

    console.log(response_json)

    const articles = document.getElementById("articles")


    //아래 코드는 for문처럼 동작된다.
    response_json.forEach(element => {
        const newArticle = document.createElement("div")		// 하나의 div를 생성
        newArticle.innerText = element.title					// div안에 text는 title을 넣는다.
        articles.appendChild(newArticle)						// 메모리 상에 만들어져 있는 데이터를 실제 html에 넣는다.

    });

}

 - 위의 코드를 작성하고 새로고침하면 백엔드에 저장된 데이터를 프론트엔드 화면에 띄워주게 된다.

 

반응형

댓글