백엔드로 django를 사용하며 rest로 구성하기 위해 공부
django는 풀스택 프레임워크이다. 즉 프론트, 백엔드를 전부 제공할 수 있다. 실제로 템플릿을 이용해 프론트를 보여주고 간단하게 그 값을 백엔드에서 활용할 수 있다. 하지만 본인은 개발 과정에서 프론트는 nextjs를 이용하고있다. 그래서 DRF를 이용해 rest한 백엔드를 구성해 프로젝트를 진행할 것이다.
https://www.django-rest-framework.org/tutorial/1-serialization/
REST하게 django를 이용하려면 json으로 데이터를 통신하는 것이 좋다. 즉 DB데이터를 json으로 json을 DB데이터로 변경하는 과정이 필요하다. 이과정을 도와주는 것이 직렬화이다.
위에서는 직렬화를 통해 DB와 잘 소통하게 했다. 그럼 프론트와 소통하려면 어떤식이 좋을까?
위에 함수를 url패턴에 적용하면 이제 endpoint로 json, html 등 원하는 방식으로 응답 받을 수있다.
CRUD를 쉽게 적용하도록 도와주는 Mixin을 이용해 APIVeiw를 쉽게 적용하도록 도와주는 방식
https://www.django-rest-framework.org/api-guide/generic-views/
위에 url에서 다양한 mixins을 통해 적절한 API를 구성할 수 있다.
class DietDetail(generics.RetrieveUpdateDestroyAPIView):
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsUserOrReadOnly]
queryset = Diet.objects.all()
serializer_class = DietSerializer
위 views.py파일의 코드를 보면 2가지의 기본 세팅이 존재한다.
바로 queryset, serializer_class이다.
먼저 queryset의 경우 queryset 속성을 설정하거나 get_queryset() 메서드로 override해서 사용해 view가 객체를 반환하도록 도와준다.
다음 serializer_class이다. 입력된 값을 validate deserialize, serialize할 때 사용, 일반적으로 이 속성을 설정하거나 get_serializer_class()메소드로 override해서 사용해야 함
DRF를 사용하며 가장 어려웠던 부분이다.
직역하면 중첩된 관계를 뜻하는데 공식문서를 보면 앨범과 트랙의 관계로 표현해준다, 앨범 속에는 여러 트랙이 있고 이것을 아래처럼 표현해준다.
class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ['order', 'title', 'duration']
class AlbumSerializer(serializers.ModelSerializer):
tracks = TrackSerializer(many=True, read_only=True)
class Meta:
model = Album
fields = ['album_name', 'artist', 'tracks']
생성시 dataform
{
'album_name': 'The Grey Album',
'artist': 'Danger Mouse',
'tracks': [
{'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
{'order': 2, 'title': 'What More Can I Say', 'duration': 264},
{'order': 3, 'title': 'Encore', 'duration': 159},
...
],
}
코드를 보면 Serializer속에서 관계를 가지는 다른 Serializer를 가져오는데 마치 Join을 보는것 같다.
내가 어려웠던 부분은 나의 경우 음식, 식단, 식단정보 3가지 테이블이 있고 식단과 식단정보는 1:n, 식단정보와 음식은 1:1의 관계를 가졌다. 여기서 식단에서 Nested, 식단정보에서도 Nested를 하다보니 저장에 어려움이 생겼다 왜나면 음식은 생성하는 것이라니라 이미 존재하는 것에서 가져오는 방식이였기 때문에 예의 트랙처럼 보낼수 없었다.
그래서 아래글을 참고해서 풀었다.
https://stackoverflow.com/questions/74606902/django-sending-post-request-using-a-nested-serializer-with-many-to-many-relati
위 글의 핵심은 읽기전용으로 쓰기전용을 따로 만들어서 사용하는 것인데 이를 통해 Serializer읽기전용으로 응답을 받고 음식쓰기용 필드를 새로 만들어서 저장했다.
class DietDetailSerializer(serializers.ModelSerializer):
foodno = FoodSerializer(read_only=True)
foodid = serializers.PrimaryKeyRelatedField(
queryset=Food.objects.all(),
write_only=True,
)
class Meta:
model = DietDetail
fields = ["dietdetailid", "foodno", "dishid", "weight", "foodid"]
ordering = ["dietdetailid"]
후기: DRF는 쉽게 처리하도록 하는 기능이 확실히 많이 있지만 기능의 기초가 되는 각 부분을 잘 이해하자.
공감하며 읽었습니다. 좋은 글 감사드립니다.