
0. 들어가기 앞서
- REST API를 이용하면 Frontend server와 Backend server로 나뉘어져 REST API로 서로 통신하면 된다. 따라서 Backend server에 Template이 없어도 된다
- 기존에 사용한 JsonResponse를 가지고 주고 받을 수 있다. 허나, 모델이 복잡해질수록 이렇게 Json 타입으로 일일이 만드는데는 어려움이 있다
- 이를 간편하게 하기 위한 도구들의 모음이 Django Restwork Frame이다
1. DRF란?
- Django Restwork Frame은 Django 안에서 Restful Api 서버를 쉽게 만들게 도와주는 open source 라이브러리다
- serializer란? 직렬화해주는 class로 Json Data는 컴퓨터 내에서는 연속적인 Data형태의 문자열로 되어있다. 이를 만들기 위해, serializer는 지정한 Model의 Data를 Json Data Type으로 저장해준다. 즉, model 객체를 Json Data로 만들어주는 Json 직렬화를 해준다
- 직렬화란? 객체의 내용을 바이트 단위와 같은 연속적인(serial) Data로 변환하여 파일 또는 네트워크를 통해서 스트림(송수신)이 가능하도록 하는 것. 이를 통해 객체를 네트워크를 통해 손쉽게 교환할 수 있다. 이 직렬화는 바이트 단위로 분해하는 marshalling과 전송 후 받은 Data를 복구하는 unmarshalling의 과정을 거친다
2. DRF 설치

- 먼저, 새 Django 프로젝트를 생성한다
- 다음 https://www.django-rest-framework.org/에 접속해 메뉴얼을 확인한다

- 그대로 pip install을 해준다

- settings.py 수정

- url 추가는 선택사항이지만 추가하면 편하다

- Text로만 나오는 Json Data들을 DRF에서 보기 편하게 구현한 page들이 들어있다

- url 끝에 '/'를 붙여야한다

- 잘 설치된 것을 확인할 수 있다
3. App 구성하여 실행해보기
- https://www.django-rest-framework.org/tutorial/1-serialization/ 를 참조한다

- App을 하나 만들고 settings.py에 추가한다

- model 추가해준다

- meta : 데이터에 대한 데이터다
- serializer.py를 생성하고, serializers class를 상속받아 class를 만들고 지정할 model과 Json type으로 바꿀 data를 fields에 넣어준다. 'all'은 model의 모든 fields를 가져온다. 이를 통해 model 객체를 Json Data Type으로 변환해준다

- 이제 view에서 render를 사용하지 않는다. rest_framework에서 viewsets을 가져온다. 이 viewsets에 CRUD가 모두 들어있어서 따로 구현하지 않아도 된다. queryset에 사용할 model을 넣고, serializer_class에 사용할 serializer를 넣는다. 즉 model에서 뽑은 queryset을 serializer에 넣어 Json type Data로 만들어준다. 이 두 가지 변수는 ModelViewSet에 저장된 객체명이다

- config의 url을 수정한다

- app에 url을 추가한다
- router는 url을 자동으로 생성해주는 도구다. 안에 이름과 viewset를 넣어주면 viewset class의 method들의 url을 product/~로 자동으로 만들어준다
- 이렇게 되면 config의 url/app밑의 url/ 라우터의 url 순으로 쳐야한다. url 이름은 자유다. 비어놔도 된다
- migrate하고 실행하면 page가 출력된다

- 관리자 페이지에서 상품을 관리할 수 있게 추가한다

- 상품을 등록하면 Json Data로 변환해준다

- 관리자 페이지에서 잘 확인된다

- 뒤에 상품의 id를 입력하면 상품 하나를 조회한다

- patch와 delete : 수정과 삭제
3. ADVANCED REST Client

- post로 상품을 저장할때, type를 json으로 하고, editor를 통해 편하게 작성할 수 있다

- 상품이 추가됬다

- 수정할 상품의 id를 url에 치고 내용과 함께 PATCH를 전송하면 수정된다
- 이 기능들이 VIEWSETS에서 제공하는 기능들이다
4. 기능 커스텀
- 기능을 커스텀해보자. ModelViewSet에 내장된 get_queryset()을 오버라이딩해야한다
- Get product 검색 모델Data.name
- get방식으로 뒤에 Data가 들어갔을때 이를 찾을 수 있도록 기존의 get_queryset에 Data 검색 기능을 추가한다

- view를 수정해준다
- super().get_queryset()을 통해 부모의 get_queryset()을 통해 queryset Data를 가져온다
- request.query_params.get은 Django에서 사용했던 request.GET.get이다

- name__contains는 찾고 싶은 단어가 포함된 목록을 불러온다. 단, 대소문자를 구분한다

- icontains는 대소문자 구분 안한다

- 잘 조회된다

- icontains했으므로 SF를 써도 대소문자 구분 없이 포함된 Data를 불러온다
- 위에서는 Get product/? name = [name] 검색목록을 구현했다
- 이번에는 get할때 뒤에 ?를 안 붙이고, 경로에 바로 Data를 입력해보자. 이는 새 기능을 추가하는 것으로 url도 새로 만들어야한다

- decorator를 사용하기 위해 action을 import한다

- action 속성 : detail이 true면 하나 조회, false면 목록, method에는 허용할 method들 정의, url_path는 사용할 url으로 search는 필자가 그냥 지정한 이름이다. 이처럼 action은 modelviewset에서 기능을 추가할때, 해당 기능에 대한 detail, method, url_path와 같은 동작과 같은 기능에 대한 속성을 정의해주는 decorator다
- name=None : name이 없다면 None으로 처리
- (?P[^/.]+) : 정규표현식으로 ()는 묶는 것, ?P<그룹이름>,^/.은 ^로 시작하며 /.은 /가 아닌 아무거나 온다는 거다. /가 아닌 뒤에 오는 Data들을 그룹에 저장하는 것이다
- 이 함수는 오버라이딩이 아닌 기능을 추가한 것 이므로 serializer를 추가해야한다. 위에 오버라이딩한 것은 부모 class에 serializer가 들어가있다
- serializer의 many는 다수의 Data가 있을때 True, 단일 Data면 False다

- 잘 검색된다
- Get product/search/[name] 검색목록을 구현했다
5. Review를 구현해보자
- GET, POST, GET ID, PATCH ID, DELETE ID를 구현해야한다
- review App을 생성해서 제작해보자

- view 구현

- App url 구현

- Config url에 추가

- model 구현

- serializer 구현

- 잘 실행된다

- ?를 통해 Data도 잘 찾아진다

- custom해서 만든 search 기능도 잘 동작된다
- score의 값을 제한해보자

- Django에는 값을 비교할 수 있는 validator가 내장되어있다. Min과 Max를 import하여 들어오는 값의 범위를 제한한다. Min(0), Max(5)를 통해 범위를 0~5로 제한할 수 있다. 이 범위 밖의 값은 들어올 수 없다
6. APIView
- Review에서 목록 조회는 필요가 없다. 허나 ModelViewSet은 CRUD의 모든 기능을 가지고 있다. 이처럼 특정 기능만 필요할때는 APIView를 사용한다. ModelViewSet은 APIView를 상속받아 DRF에서 만든 것이다
- APIView는 CRUD를 다 가지고 있는 것이 아닌, 필요한 특정 기능만 사용할 수 있다

- APIView를 import 한다

- 사용할 기능을 구현한다. URL 하나에 class 하나이다. 즉 URL 하나에 기능 하나이다. 이 각각의 기능들 안에 GET, POST등을 구현할 수 있다
- as_view() : 메소드 핸들러로 이는 클래스 인스턴스를 생성해서 dispatch()를 실행하여 url에 대한 method에 대해 알아내고, 해당 인스턴스 내부에 해당 이름을 가지고 있는 method로 요청해준다. 해당 method가 없으면 예외 발생한다. 이 기능을 ModelViewSet은 APIView를 상속받아 내부에 기능을 추가했으므로, 앞에서는 사용하지 않았다

- App url에 추가한다. 만약 URL 뒤에 숫자(pk값)이 들어가면 아래 단일 Data를 get하는 함수가 작동한다
- 이처럼, CRUD가 다 필요하면 ModelViewSet, 특정 기능만 필요하면 APIView, 기능을 커스텀하고 싶으면 상속받아 오버라이딩하면 된다

- 잘 실행된다
7. METHOD 추가
- 목록에 추가 (POST) 를 구현하고, 단일 Data에 수정 (PUT), 삭제 (DELETE)를 구현하면 된다
7.1 POST

- serializer가 form 역활도 해준다. 따라서 is_valid와 save가 가능하다
- is_valid가 되면 상태코드 201을 보내주고, 실패하면 상태코드 400을 보내준다
- list로 다수의 data를 입력하면 many를 True로, 하나의 data면 False로 설정해야한다

- 성공시

- 실패시
7.2 PUT, DELETE

- APIView에서는 수정이 PUT이다
- qs와 data를 serializer에 넣어 qs를 data로 수정할 수 있게한다

- 잘 작동된다

- url을 주의하자. 만약 reviewapi의 url이 review라면 viewset를 호출하는 라우터 주소인 review와 겹쳐서 다른 기능이 실행될 수 있다. 즉 일반 review 주소와 app 주소 " " + 라우터 주소 "review" 인 review가 중복된다

- 전체 필드가 아닌 특정 필드만 입력해도 수정이 되게 한다. 원래 두 가지 필드를 다 입력해야하지만, partial을 True로 하면 부분적으로만 입력해도 해당 필드가 수정된다

- 잘 실행된다
8. 회원 구현 환경 설정
- token 로그인 : 로그인 정보가 클라이언트에게 저장
- session 로그인 : 로그인 정보가 서버에 저장
- token 로그인과 session 로그인 방식은 다음 장에서 자세히 다루겠다
- rest api를 이용해서 로그인 구현

- 새 app을 만든다

- allauth 설치 - 소셜 로그인용이다

- Dj-rest-auth 설치. rest-auth는 지원이 끝나서 발전형인 Dj-rest-auth를 설치한다 ( 참고. https://dj-rest-auth.readthedocs.io/en/latest/installation.html )

- Installed_app에도 순서가 있다. 따라서 참조하는 app이 밑으로 가게 한다

- contrib.sites를 추가했으므로 SITE_ID를 추가한다
- 기능을 추가했으니 migrate 해주자

- url 추가

- 여기까지해서 사용하면 Session 로그인 방식이다. 이를 Token 로그인 방식으로 바꿀려면 설정해줘야한다