HTTP 요청
- 200 : GET 요청 성공
- 201 : POST 요청 성공
- 400 : Client 요청이 잘못됨
- 401 : 인증이 되어 있지 않음
- 403 : 처리할 권한이 없음
- 404 : URL (리소스) 가 존재하지 않음
- 500 : Server에서 문제가 생김
- 503 : Server에서 요청 처리를 못함 (잠깐 사용 못함)
URI : 통합 자원 식별자, 웹상에 자원이 어디 있는지 나타내기 위한 문자열
RestFul API : URL로 소통하는 것
URL은 동사가 아닌 명사의 나열로 사용해야 함
(POST /articles/create 가 아닌 POST /articles/ 로 사용해야 함)
Author이 게시글 생성일 때에 필요가 없기 때문에 readonlyField로 해줘야 함
클래스 기반으로 처리를 함
함수형 View
1. view 어노테이션을 달아준다.
2. view method를 선택한다.
3. object를 불러온다.
4. serializer를 불러와 Response 표출 혹은 유효성 검증을 함
Serializer에서 들어가는 객체가 여러개일 경우 many=True 옵션을 줘야 함
POST 즉 생성의 요청의 경우에는 serializer.save() 요청이 필요함
예시 코드 CRUD
@api_view(["GET"])
def json_drf(request):
articles = Article.objects.all()
# Serializer에 들어가는 객체가 여러 개이기 때문에 many=True 옵션을 줘야 힘
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
@api_view(["GET", "POST"])
def article_list(request):
if request.method == "GET":
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == "POST":
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data, status=201)
@api_view(["GET", "PUT", "DELETE"])
def article_detial(request, pk):
if request.method == 'GET':
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
elif request.method == "PUT":
article = get_object_or_404(Article, pk=pk)
serializer = ArithmeticError(article, data=request.data, partial=True)
elif request.method == "DELETE":
article = get_object_or_404(Article, pk=pk)
article.delete()
return Response(status=200)
SEEDING을 이용한 더미 데이터 생성
python3 manage.py seed articles --number=20
Access Token VS Refresh Token
Access Token
- 요청할 때 인증을 위해 헤더에 포함해야 하는 토큰
- 매 요청 시 보내는 토큰으로 보안에 취약함
- 만료 기한을 짧게 잡아 만약 탈취 당해도 짧은 시간안에 유효하지 않은 토큰 형태가 됨
Refresh Token
- Access Token이 만료되었을 때 Access Token을 발급하기 위한 Token
- Access Token보다 긴 유효기간을 가짐
- 주로 사용자의 기기에 저장해두고 사용되며 만약 Refresh Token까지 만료되었다면 다시 인증(로그인) 과정이 필요함
- Refresh Token의 탈취를 보완하기 위해 DB 리소스를 사용하는 다양한 방식도 존재 (BlackList 등)
조건 연결 -> Q() 이용
Product.objects.filter(Q(price__get=15000) | Q(quantity__lt=3000))
필드값 가져오기 -> F()
Products.objects.update(price = F('price') + 1000)
추가적인 정보를 제공하는 데 사용하기 -> annotate()
# total_price = price * quantity
products = Product.objects.annotate(
total_price = F('price') * F('quantity')
)
종합/집약하는 데 사용하기 -> aggregate()
products = Product.objects.all()
products.aggregate(Avg('price'))
# 평균 이름을 지정해주고 싶다면
products.aggregate(avg_price=Avg('price'))
카테고리형으로 뽑는 방법 -> group_by()
products.values('category')
products.values('category').annotate(Count('category'))
다만 지연로딩은 관련된 모델을 가져와야 하는 작업이 필요할 경우에는 N+1 Problem이 발생함
select_related
- 정참조
EX.
Comment.objects.all().select_related("article")- one-to-many 또는 one-to-one 관계에서 사용
- SQL의 JOIN을 이용해서 관련된 객체들을 한 번에 로드하는 방식
prefetch_related
- many-to-many 또는 역참조 관계에서 주로 사용
(select_related를 사용하는 관계에서도 동작)- 내부적으로 두번의 쿼리를 사용해서 동작
첫번째 쿼리는 원래 객체를 조회하며 두 번째 쿼리는 연관된 객체를 가져오는 방식
ModelClass.object.filter(조건절)
.selected_related('정방향 참조') # JOIN
.prefetch_related('역방향 참조') # Additional Query
Query를 손쉽게 로그하려면?
pip install django-silk MIDDLEWARE에 'silk.middleware.SilkyMiddleware', 추가 urlpatterns += [path("silk/", include("silk.urls", namespace="silk"))]
