코딩 개발일지

장고(Django) serializer / class view / CORS 본문

AI 본 교육/AI 7주차

장고(Django) serializer / class view / CORS

호기호 2023. 9. 19. 17:34

시리얼라이저 : 딕셔너리 형태로 일일히 작성해주는건 너무 비효율 적이기 때문에, JSON 형태로 만들어주는 것.

 

serializer.py 를 만들고 작성해준다.

from articles.models import Article
from rest_framework import serializers


class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = "__all__"

그러면, views.py에 있는 함수에서 딕셔너리를 간단하게 바꿔 쓸 수 있다. 아래코드는 serializer 안쓴 코드

@api_view(('GET', 'POST'))
def index(request):
    articles = Article.objects.all()
    article = articles[0]
    article_data = {
        "title": article.title,
        "content": article.content,
        "created_at": article.created_at,
        "updated_at": article.updated_at,
    }
    return Response(article_data)

article_data 대신 

@api_view(('GET', 'POST'))
def index(request):
    articles = Article.objects.all()
    article = articles[0]
    serializer = ArticleSerializer(article)
    return Response(serializer.data)

를 넣어줄 수 있고, 위 코드는 article[0] 한개만 가져 오는 것이고, 아래 코드는 전부 가져오는 것이다.

Response 뒤에 serializer.data data 까먹지 말기

@api_view(('GET', 'POST'))
def index(request):
    articles = Article.objects.all()
    serializer = ArticleSerializer(articles, many=True)
    return Response(serializer.data)

many=True 써줘야 다 가져옴.

 

위 코드는 GET일 때의 코드기 때문에 if request.method == 'GET': 를 넣어준다.

save를 post하는 함수도 만들어주고, 유효성 검사도 해줘야한다. (is_valid)

    elif request.method == 'POST':
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            print(serializer.errors)
            return Response(serializer.errors)

이건 기능들을 웹주소에 입력해서 연결 후 이용할 수 있지만, '포스트맨'을 써서 보기좋고 쉽게 이용 가능하다.

 

POST 되는것은 Body부분에서 raw, JSON으로 꼭 바꿔줘야한다.

그리고 environment 탭에서 initial value 칸에 이용할 기본 웹주소 명을 넣어서 쓸 수 있다.

{{ }}로 넣어주면 됌.

수정기능, 삭제기능도 추가해주자. PUT도 당연히 raw / JSON 적용


views.py에서 class형 view를 작성할 수 있는데, 그냥 함수로 쓰면 되는거 아닌가요?? 할 수 있지만, 장고의 여러 기능이나 다른 class를 상속 받을 수 있기 때문에 class형 view가 좋다고 한다.

https://www.django-rest-framework.org/tutorial/3-class-based-views/

 

3 - Class based views - Django REST framework

We can also write our API views using class-based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code DRY. We'll start by rewriting the root view as a cla

www.django-rest-framework.org

공식문서에서 import와 기본적인 양식을 복사해서 쓰면 된다.

get과 post의 내용은 기존 함수에서 가져다 쓰면 된다.

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도 당연히 바꿔줘야 하는데,

views.index로 연결되던 것을

path('', views.ArticleList,as_view(), name="index"),

이렇게 바꿔줘야 한다. views.클래스명.as_view()


프론트엔드는 그동안 새로운 파일에 관리를 안했는데, 따로 관리하는게 좋을 것 같다.

html과 javascript를 <head>의 <script> 안에 넣어서 불러 올 수 있다.

<script src="index.js"></script>

이렇게 불러올 수 있고, 그럼 우리가 아까 장고로 만든 웹사이트를 연결해줄 수 있겠다???라는 생각을 할 수 있다.

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)
}

index.js 에 이렇게 작성해주고 콘솔창을 가보니, 에러가 떠 있었다.

아주 중요한 에러이고, CORS는 면접 단골 질문이라고 한다!!!!

 

브라우저에서는 보안적인 이유로 cross-origin HTTP 요청들을 제한합니다. 그래서 cross-origin 요청을 하려면 서버의 동의가 필요합니다. 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절합니다.

이런 매커니즘을 CORS(Cross-Origin Resource Sharing)라고 한다.

CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 됩니다. 

 

cors는 아래 사이트에서 하라는대로 해서 해결할 수 있다.

https://pypi.org/project/django-cors-headers/

 

django-cors-headers

django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS).

pypi.org

settings.py에 추가할 때, middleware부분에서 작성 순서가 중요하다. 위 사진과 같은 순서로 필수!!