어제 정리한 APIView
를 직접 사용해보려고 한다.
model
은 이전 프로젝트에서 작성해둔 것을 쓸 것이다.
# user/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser, PermissionsMixin
# AbstractUser 상속 / setting.py에 AUTH_USER_MODEL = '앱이름.클래스이름' 써줘야 한다
class User(AbstractUser, PermissionsMixin):
class Meta:
ordering = ['date_joined']
# 이두 운동 관련된 모델
class BicepsCurl(models.Model):
username = models.CharField(max_length=25)
count = models.IntegerField()
count1 = models.IntegerField()
count2 = models.IntegerField()
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return ("TotalCount:"+str(self.count)+" LCount:"+str(self.count1)+
" RCount:"+str(self.count2)+" time:"+str(self.times)+" day:"+self.day)
class Meta:
ordering = ['created']
# 스쿼트 운동 관련 모델
class Squat(models.Model):
username = models.CharField(max_length=25)
count = models.FloatField(max_length=255)
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "Count:"+str(self.count)+" Time:"+str(self.times)+" Date:"+self.day
class Meta:
ordering = ['created']
# 푸쉬업 운동 관련 모델
class PushUp(models.Model):
username = models.CharField(max_length=25)
count = models.FloatField(max_length=255)
sum_times = models.IntegerField(null=True)
sum_count = models.IntegerField(null=True)
times = models.FloatField(max_length=255)
title = models.CharField(max_length=255, null=True)
day = models.CharField(max_length=255, null=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "Count:"+str(self.count)+" Time:"+str(self.times)+" Date:"+self.day
class Meta:
ordering = ['created']
사실상 모든 운동 모델이 거의 동일하다.
사용자 이름 / 횟수 / 운동 시간 / 요일 / 날짜 등을 받아서 정리한다.
모든 요청에는 insomnia REST Client를 사용할 것이다.
# user/views.py: Class Based View 작성하기
# 이두 운동 데이터에 대해
class BicepsListAPIView(APIView):
# get 요청이 들어왔을 때
def get(self, request):
# BicepsCurl 모델의 데이터를 직렬화 / 필드값이 복수일 때 many=Ture
serializer = BicepsSerializer(BicepsCurl.objects.all(), many=True)
# 직렬화한 데이터를 반환
return Response(serializer.data)
# user/urls.py: 위에 작성한 View에 url 붙여주기
...
path('BicepsListAPIView/', BicepsListAPIView.as_view())
...
이렇게 해놓고 해당 주소로 get
요청을 보내면
이렇게 저장해둔 기록들이 주르륵 잘 나오는 것을 볼 수 있다.
혹시 get
요청을 보내면서 body
부분에 'username'을 첨부하면 해당 사용자의 기록을 볼 수 있을까?
# user/views.py: 이전 코드를 조금만 수정
# 이두 운동 데이터에 대해
class BicepsListAPIView(APIView):
# get 요청이 들어왔을 때
def get(self, request):
# request의 body에서 username에 해당하는 데이터를 get_username 변수에 할당
get_username = request.data['username']
# BicepsCurl 모델의 데이터를 직렬화 / 필드값이 복수일 때 many=Ture
# serializer = BicepsSerializer(BicepsCurl.objects.all(), many=True)
# get_username과 일치하는 username의 BicepsCurl 기록을 직렬화
serializer = BicepsSerializer(BicepsCurl.objects.filter(username=get_username), many=True)
# 직렬화한 데이터를 반환
return Response(serializer.data)
이렇게 코드를 바꾸고 get
요청을 하면서 body
에 'username'을 넣으면?
된다...🤔 이야.. 좋은 것 같다!
이게 안 돌아갔으면 FBV로 돌아갔어야 했는데 아주 잘 처리가 된다.
이렇게 되면 post 멤버 함수
에는 기록 생성 기능을 넣을 수 있게 됐다.
def post(self, request):
...
위와 같은 함수를 class BicepsListAPIView(APIView):
의 멤버함수로 작성해줄 것인데, 예제 코드를 확인해보면 .is_valid():
메서드를 흔하게 볼 수 있다. 어설프게나마 완료한 프로젝트에서도 이 메서드를 사용하긴 했지만 제대로 알고 넘어간다면 도움이 될 것 같다.
그러므로 살펴본다. django serializer부터. 초심초심.
지금부터의 내용은 다음의 링크들을 보고 공부하며 작성한다.
두 분 모두 공식문서를 참고하여 작성해주셨다.
이하 내용은 아마도 거의 복붙 수준일 것이다..
미리 감사의 인사 드립니다.
감사한 마음으로 받아 먹겠습니다. 🙇🏻♂️
모든 프로그래밍 언어의 통신에서, 데이터는 반드시 문자열로 표현되어야만 한다.
송신자: 객체를 문자열로 변환하여 전송
이 과정을 직렬화라고 한다.
수신자: 수신한 문자열을 다시 객체로 변환하고 이를 활용한다
이 과정을 비직렬화라고 한다.
비직렬화는 수신한 문자열을 다시 객체로 변환하고 이를 활용한다고 되어 있다.
이 과정은 다음과 같이 정리할 수 있다.
parse
를 사용하여 Python자료형
으로 변환validator
를 사용하여 유효성 검증대표적인 직렬화 포맷에는 JSON, XML이 있다.
JSON에 대해서도 간단히 살펴봐야겠다.
JavaScript Object Notation.
JSON은 문자열 형태로 존재한다.
따라서 네트워크를 통해 전송할 때 아주 유용하다.
🔎 문자열을 네이티브 객체로 변환하는 것을 파싱(Parsing)이라고 한다.
네트워크를 통해 전달할 수 있도록 객체를 문자로 변환하는 과정은 문자열화(Stringification)이라고 한다.개별 JSON 객체를
.json
확장자의 단순 텍스트 파일에 저장할 수 있다.
MIME 타입은application/json
이다.
JavaScript 객체 리터럴 문법을 따르는 문자열이다.
따라서 JavaScript의 기본 데이터 타입인 문자열
, 숫자
, 배열
, 참과 거짓
그리고 기타 객체
를 포함할 수 있다.
{
"squadName": "Super hero squad",
"homeTown": "Metro City",
"formed": 2016,
"secretBase": "Super tower",
"active": true,
"members": [
{
"name": "Molecule Man",
"age": 29,
"secretIdentity": "Dan Jukes",
"powers": [
"Radiation resistance",
"Turning tiny",
"Radiation blast"
]
},
{
"name": "Madame Uppercut",
"age": 39,
"secretIdentity": "Jane Wilson",
"powers": [
"Million tonne punch",
"Damage resistance",
"Superhuman reflexes"
]
},
{
"name": "Eternal Flame",
"age": 1000000,
"secretIdentity": "Unknown",
"powers": [
"Immortality",
"Heat Immunity",
"Inferno",
"Teleportation",
"Interdimensional travel"
]
}
]
}
기본적으로 중괄호{}안에 쌍따옴표("")와 콤마(,) 그리고 대괄호[]로 구성된다.
CDN 문서에 너무나 기막히게 잘 설명되어 있는데, 이건 한번 따라해볼 만한 것 같다.
권태형 개발 블로그: [해설과 함께 읽는 DRF 문서] Validation에 기가막힌 설명글이 있다.
감사합니다. 🙇🏻♂️
"데이터를 역직렬화 할 때, 유효성이 보장된 데이터에 접근 하거나, 객체 인스턴스를 저장하기 전에 is_valid()
호출하는 것은 필수이다"라는 설명을 볼 수 있다.
앞서 .is_valid()
는 유효성 검증을 위한 과정이라고 했다.
결론부터 말하자면 serializer.data
에 접근하기 위해서는 반드시 .is_valid()
가 선행되어야 한다.
이는 흔히 create 혹은 update 동작에 대해서 외부로 부터 전해져온 데이터의 유효성 검사가 완료되어야만 데이터를 생성하고 업데이트를 하는 것과 같은 맥락에서 이해할 수 있다.
이만큼 정리했으니 다시 APIView를 짜볼 것이다.
알고 하는 거랑 모르고 하는 건 천지차이 같다.. 🤔
글의 초반부에 이미
class CBV(APIView):
def get(self, request):
...
이렇게 APIView
를 상속받은 CBV
를 작성해보았고, get
요청에 body
를 첨부해도 django는 알아서 잘 처리해준다는 것을 볼 수 있었다.
Unity 및 이에 사용되는 C# 스크립트를 메인으로 사용하는 프로젝트를 진행하면서, Http Request
를 사용해봤는데 생각보다 안 되는 것이 많았다. get
요청에 body
를 넣으면 에러가 난다든지.. 물론 HttpWebRequest
와 같은 클래스를 사용하면 또 에러가 나지 않았다. 자동으로 처리해주기 때문에..
아무튼 APIView
를 상속하는 것임에도 이런 디테일한 자유도가 있다는 건 좋은 것 같다.
genericAPIView
를 사용하여 아주 간편하게 처리할 수 있는 기능은 추후에 다뤄보는 것으로 하고, FBV
에 @데코레이터
들을 섞어 쓸 수 있는 방법을 배워보고 싶다.
일일이 뭔가 설정해줘야 하는 것은 다소 불편함이 있을 수 있지만, 인증
이나 권한
에 관한 최소한의 상속을 받으면서 최대한 자유롭게 코드를 짤 수 있는 방향에 흥미가 가는 듯하다.
다음은 @데코레이터
를 살펴보겠다.
도움주신 귀한 분들 다시 한 번 감사합니다. 🙇🏻♂️
감사합니다.