본문 바로가기

프로그래밍/Django개발(MAC OS)

Django Rest API 서버 만들기 요약 - Day 1

반응형

Django를 활용하여 REST API 서버를 만드는 방법에 대해서 정리하기 위한 포스팅입니다.

개인적으로 사용하기 위한 것이라ㅠㅠ 정보 전달보다는 전체적으로 어떻게 학습 했는지를 봐주시면 좋을 것 같습니다.

공부했던 내용 순으로만 작성해보았습니다.

  1. Django restframwrok 설치
    - https://www.django-rest-framework.org/#installation
  2. api view 사용
    - rest_framework.decorator api_view 를가지고와서
    - @api_view를사용하면됨
    - 예를들어@api_view(['GET', 'POST']) 이런식으로만들면

  3. Serializers를사용 ->Serializers.py 파일을 생성하여 이곳에 Serializer할 내용들을 입력
    - serializerValidation과다가능함
#serializers.py

from rest_framework import serializers


class RoomSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=140)
    price = serializers.IntegerField()
    bedrooms = serializers.IntegerField()
    instant_book = serializers.BooleanField()

  - Views.py에서 Serializer를 불러오기

#views.py

from .models import Room
from .serializers import RoomSerializer

@api_view(["GET","DELETE"])
def list_rooms(request):
    rooms = Room.objects.all()
    serialized_rooms = RoomSerializer(rooms, many=True)
    return Response(data=serialized_rooms.data)

 

  • Serializer에 ModelSerializer를 활용하면 더욱 간단하다.
    - ModelSerializer를 상속받아오면 Meta Tag를 활용하여 원하는 필드의 값들만을 추출 할 수 있음.
    - 근데 예제에서 아래의 User의 id 값을 얻고 싶은 것이 아닌 User의 username이나 권한등을 얻어오고 싶다면,
    - TinyUserSerializer를 User App에서 Serialziers.py를 생성하여 값을 가져오면 된다.
#rooms/serializers.py

from rest_framework import serializers
from users.serializers import TinyUserSerializer
from .models import Room

class RoomSerializer(serializers.ModelSerializer):
    
    user = TinyUserSerializer()

    class Meta:
        model = Room
        fields = ("name", "price", "instant_book", "user")

 

#users/serializers.py

from rest_framework import serializers
from .models import User


class TinyUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ("username", "superhost")
  • Generic View를 활용해보자
    - Generic View를 활용하면 더욱 간편하게 값들을 읽어 올 수 있다.

    - view를 LisetAPIView를 활용해서 사용하기 위해서는 rest_framwork.generics > ListAPIView를 가져오고
#rooms/views.py

from rest_framework.generics import ListAPIView

from .models import Room
from .serializers import RoomSerializer


class ListRoomsView(ListAPIView):
    queryset = Room.objects.all()
    serializer_class = RoomSerializer

 

 

Pagination - Django REST framework

pagination.py Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links. — Django documentation REST framework includes support for customizable pagination styl

www.django-rest-framework.org

 

#settings.py

REST_FRAMEWORK = {
    "DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
    "PAGE_SIZE": 10,
}

https://www.cdrf.co/3.13/rest_framework.generics/ListAPIView.html

 

ListAPIView -- Classy DRF

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] View

www.cdrf.co

자세한 내용들을 위에 링크에 나와있습니다.

 

 

  • DetailView API만들어보기
    - ListVIew를 만든 이후에는 Detail View를 만들어 보도록 하면 됩니다.
    - Detail View도 Generic에 RetrieveApiView를 활용하여 만들어 보면 됩니다.
#rooms/views.py

from rest_framework.generics import ListAPIView, RetrieveAPIView

from .models import Room

...

class SeeRoomView(RetrieveAPIView):
    queryset = Room.objects.all()
    serializer_class = BigRoomSerializer

 

#rooms/serializers.py

class BigRoomSerializer(serializers.ModelSerializer):
    class Meta:
        model = Room
        exclude = ()

 

  • 방금 했던 위의 내용들을 아주 간단히 하기위해서는 viewset이라는 것을 사용하면 아주 간단하게 사용할 수 있다!!  viewset을 사용하는 방법은 restframworks에서 보면 되지만, 너무 간편해서 무섭다. 최대 큰 단점은 Viewset은 모든 것들을 한번에 제공해주기 때문에 보안적인 부분이 상당히 취약하다 -> 하지만 결국 Viewset으로 구축하면 너무 간편하다! 

 

  • POST를 사용하기 위해서는 먼저 FBV로 POST를 해보도록 하자

- 앞서 했던 것처럼 api_view Decorator를 활용해서 Function Based View로 만들어준 다음에 GET 방식과 POST방식으로 분기 처리를 해준다.
- 그리고 GET방식의 경우의 Serializer와 POST방식의 Serializer를 만들어 준다.

#rooms/views.py

from rest_framework.decorators import api_view
from rest_framework.response import Response

...

@api_view(["GET", "POST"])
def rooms_view(request):
    if request.method == "GET":
        rooms = Room.objects.all()
        serializer = ReadRoomSerializer(rooms, many=True).data
        return Response(serializer)
    elif request.method == "POST":
        serializer = WriteRoomSerializer(data=request.data)
        if serializer.is_valid():
            return Response(status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

WriteSerializer는 ModeilSerialzier말고 그냥 Serializer로 한번 가져와보자.

#rooms/serializers.py

class WriteRoomSerializer(serializers.Serializer):

    name = serializers.CharField(max_length=140)
    address = serializers.CharField(max_length=140)
    price = serializers.IntegerField()
    beds = serializers.IntegerField(default=1)
    lat = serializers.DecimalField(max_digits=10, decimal_places=6)
    lng = serializers.DecimalField(max_digits=10, decimal_places=6)
    bedrooms = serializers.IntegerField(default=1)
    bathrooms = serializers.IntegerField(default=1)
    check_in = serializers.TimeField(default="00:00:00")
    check_out = serializers.TimeField(default="00:00:00")
    instant_book = serializers.BooleanField(default=False)

 

  • POST 방식으로 Room 데이터를 추가 해보도록 합니다.

#rooms/serializers.py

class WriteRoomSerializer(serializers.Serializer):

    name = serializers.CharField(max_length=140)
    address = serializers.CharField(max_length=140)
    price = serializers.IntegerField()
    beds = serializers.IntegerField(default=1)
    lat = serializers.DecimalField(max_digits=10, decimal_places=6)
    lng = serializers.DecimalField(max_digits=10, decimal_places=6)
    bedrooms = serializers.IntegerField(default=1)
    bathrooms = serializers.IntegerField(default=1)
    check_in = serializers.TimeField(default="00:00:00")
    check_out = serializers.TimeField(default="00:00:00")
    instant_book = serializers.BooleanField(default=False)


    def create(self, validated_data):
        return Room.objects.create(**validated_data)

 

@api_view(["GET", "POST"])
def rooms_view(request):
    if request.method == "GET":
        rooms = Room.objects.all()[:5]
        serializer = ReadRoomSerializer(rooms, many=True).data
        return Response(serializer)
    elif request.method == "POST":
        if not request.user.is_authenticated:
            return Response(status=status.HTTP_401_UNAUTHORIZED)
        serializer = WriteRoomSerializer(data=request.data)
        if serializer.is_valid():
            room = serializer.save(user=request.user)
            room_serializer = ReadRoomSerializer(room).data
            return Response(data=room_serializer, status=status.HTTP_200_OK)
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)

위의 코드를 보면 우선 POST 방식일 경우에 User의 인증 여부를 먼저 확인 한다음, is_valid()값이 참이면 serializer.save() 매서드를 호출하였습니다. create를 하지 않은 이유는 serializers는 바로 create, update함수를 직접 호출하는 것이 아닌 save매서드가 그 역할을 대신 수행해주기 때문입니다. 인자로 request.user instance를 넘겨주면 create함수에 validated_data에 자동으로 들어가게 됩니다. 

 

그럼 다음 시간에는 방 디테일을 보는 것을 해보도록 하겠습니다.!

 

반응형