[Django/DRF - 상품, 리뷰 API 만들기]

SooYeon Yeon·2022년 7월 2일
0

Django

목록 보기
17/20

Django Rest Framework

새 프로젝트 생성

pip install django

django-admin startproject config .

pip install djangorestframework
pip install markdown       # Markdown support for the browsable API.
pip install django-filter  # Filtering support

settings.py에 추가

INSTALLED_APPS = [
    ...
    'rest_framework',
]

urls.py

  • 없어도 되긴하는데 예쁘게 보여줄 수 있게, 쉽게 다룰 수 있게 하는 것
urlpatterns = [
    ...
    path('api-auth/', include('rest_framework.urls'))
]

서버 실행 후

http://127.0.0.1:8000/api-auth/login/

로 확인. 뒤에 / 붙여야 뜸

앱 만들기

python .\manage.py startapp product

모델 만들기

from django.db import models

# Create your models here.

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    price = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)

앱 안에 파이썬 파일 생성

  • 모델을 직렬화시키려고 상속받아옴

serializer.py

from rest_framework import serializers

from product.models import Product

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__' # 전부다 넣고싶을 때, 각각 넣으려면 [ ]

메타데이터 - 데이터에 대한 데이터

views.py

from rest_framework import viewsets

from product.models import Product
from product.serializer import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

url

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('', include('product.urls')),
]

product폴더 안에 urls.py 만들기

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
import product.views

router = DefaultRouter()
router.register('product', product.views.ProductViewSet) # viewset이 만든 여러 메소드의 url을 만들어줌
urlpatterns = [
    path('', include(router.urls))
]

url 순서 : configurl등록-product url 등록-router url

검색 시 http://127.0.0.1:8000/product/ (뒤에 슬래시 잊지말기)

만약 config url에서 ‘abc’, product url이 ‘def’, router을 ‘ghi’로 했다면 주소창에는 ~~~/abc/def/ghi/ 로 검색

관리자에 product 등록 - admin.py (장고에서배운거)

from product.models import Product

admin.site.register(Product)

127.~~/product/1/ 이런식으로 하면 1번거 볼 수 있음. 장고 admin에서 상품추가 가능

https://chrome.google.com/webstore/detail/advanced-rest-client/hgmloofddffdnphfgcellkdfbfbjeloo 이걸 이용해 할 것임 요청 보내고 할 수 있음

(postman)도 있음

Advanced REST client 이용

Product

GET

  • 목록 받아오기

GET

  • 특정 상품 받아오기

POST

  • 상품 추가

PATCH

  • 상품 수정

DELETE

  • 상품 삭제하기

GET

  • 이름으로 검색하기
  • 장고에서의 request.GET.get(’name’)과 같은 것
  • 사용자가 ?name= 이런식으로 받을 때 사용법

views.py 내용 작성

from rest_framework import viewsets

from product.models import Product
from product.serializer import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    
    def get_queryset(self):
        qs = super().get_queryset() # 부모 거 그대로 가져온 것

        search_name = self.request.query_params.get('name',) # 장고에서의 request.GET.get('name') 와 같은 것
        if search_name:
            qs = qs.filter(name=search_name)
        return qs

  • 대소문자 구분해서 포함 되는 것 검색 : name__contains
def get_queryset(self):
        qs = super().get_queryset() # 부모 거 그대로 가져온 것

        search_name = self.request.query_params.get('name',) # 장고에서의 request.GET.get('name') 와 같은 것것
        if search_name:
            qs = qs.filter(name__contains=search_name)
        return qs
  • 대소문자 구분없이 포함 되는 것 검색 : name__icontains
def get_queryset(self):
        qs = super().get_queryset() # 부모 거 그대로 가져온 것

        search_name = self.request.query_params.get('name',) # 장고에서의 request.GET.get('name') 와 같은 것것
        if search_name:
            qs = qs.filter(name__icontains=search_name)
        return qs

함수로 처리하기

  • ?name=이 아닌 /func 이런식일 때 처리

views.py 클래스 안에서

@action(detail=False, methods=['get'], url_path="search/(?P<name>[^/.]+)") # 여러개면 detail False, method는 현재 우리는 get으로만 할거니까 get만 추가해놓음, url은 정규표현식으로 찾음. 슬래시로 시작하고 그 뒤에 아무거나 라는 뜻의 정규표현식
    def search(self,request, name=None):
        qs = self.get_queryset().filter(name__icontains=name) # name을 받아서 filter, 이건 상속오버라이딩 아님
        serializer = self.get_serializer(qs, many=True)
        return Response(serializer.data)

Review

  1. 앱 생성

    1. python .[manage.py](http://manage.py/) startapp review
  2. 모델 생성

    from django.db import models
    from django.core.validators import MinValueValidator, MaxValueValidator
    # Create your models here.
    class Review(models.Model):
        score = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(5)]) # 0최소값, 5최대값으로 설정해 리뷰 0~5점까지 받도록
        contents = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
  3. migrate

    1. python .\manage.py makemigrations
    2. python .\manage.py migrate
  4. 앱 안에 serializer.py 생성

    from rest_framework import serializers
    
    from review.models import Review
    
    class ReviewSerializer(serializers.ModelSerializer):
        class Meta:
            model = Review
            fields = '__all__'
  5. views.py

    from django.shortcuts import render
    
    # Create your views here.
    from rest_framework import viewsets
    
    from review.models import Review
    from review.serializer import ReviewSerializer
    
    class ReviewViewSet(viewsets.ModelViewSet):
        queryset = Review.objects.all()
        serializer_class = ReviewSerializer
  6. settings.py

    1. INSTALLED_APP에 review app과 rest framework사용에 대한 정보 넣기(초기설정)
    2. url도 초기설정 확인
    3. url 추가
    path('', include('review.urls')),
  7. review 폴더에 urls.py 생성

    from django.urls import include, path
    from rest_framework.routers import DefaultRouter
    
    import review.views
    
    router = DefaultRouter()
    router.register('review', review.views.ReviewViewSet)
    urlpatterns = [
        path('', include(router.urls))
    ]
  8. admin에 추가

    from django.contrib import admin
    
    # Register your models here.
    from review.models import Review
    
    admin.site.register(Review)from django.urls import include, path
  9. Advanced REST Client에서 실행해보기

    1. 리뷰 목록
      1. Method : GET
      2. Request URL : http://127.0.0.1:8000/review/
      3. SEND
    2. 리뷰 등록
      1. Method : POST
      2. Request URL : http://127.0.0.1:8000/review/
      3. Parmaeter Body - 데이터 타입 맞추어 입력
      4. SEND
    3. 리뷰 조회
      1. Method : GET
      2. Request URL : http://127.0.0.1:8000/review/1/
      3. SEND
    4. 리뷰 삭제
      1. Method : DELETE
      2. Request URL : http://127.0.0.1:8000/review/1/
      3. SEND
    5. 리뷰 수정
      1. Method : PATCH
      2. Request URL : http://127.0.0.1:8000/review/2/
      3. Parameters Body - 데이터 수정
      4. SEND

ModelViewSet은 해당 5목록이 무조건 만들어지게 되는데, 기능 하나 또는 두개만 하고싶을 때는 ModelViewSet 말고 APIView를 상속받아 오면 됨.

ModelViewSet

  • 해당 5가지 목록 모두 필요할 때 상속 Override해서 고쳐쓰면 됨

APIView

  • 특정 몇개만 사용하고 싶을 때

APIView 이용

  • 원하는 기능만 사용할 수 있도록 함

views.py

from django.shortcuts import render

# Create your views here.
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response

from review.models import Review
from review.serializer import ReviewSerializer

class ReviewList(APIView):
    def get(self, request):
        qs = Review.objects.all()
        serializer = ReviewSerializer(qs, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = ReviewSerializer(data=request.data, many=False) # 리스트로 여러개 작성할거면 many=True로 하면 됨. 리뷰에서는 2개 동시에 다는 일 없어서 False지만 상품 구매일때 여러개 살때는 True로 해도ㅗ 됨
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)

class ReviewDetail(APIView):
    # 목록 불러오기
    def get(self, request, pk): # pk는 primary key
        qs = Review.objects.get(id=pk)
        serializer = ReviewSerializer(qs, many=False)
        return Response(serializer.data)

    def patch(self,request,pk):
        qs = Review.objects.get(id=pk)
        serializer = ReviewSerializer(qs, data=request.data, partial=True) # 모델속성 다 입력안해도 수정할 수 있게 주려면 partial
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        qs = Review.objects.get(id=pk)
        qs.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

reviews의 urls.py 설정

from django.urls import include, path
from rest_framework.routers import DefaultRouter

import review.views

urlpatterns = [
    path('review/', review.views.ReviewList.as_view()),
    path('review/<int:pk>',review.views.ReviewDetail.as_view())
]

목록 확인

목록 등록

목록 하나 확인

내용 정리

product

메소드URL설명데이터
GETproduct/목록X
POSTproduct/생성Product 모델
GETproduct/[id]/조회X
PATCHproduct/[id]/수정Product 모델
DELETEproduct/[id]삭제X
GETproduct/?name=[name]검색목록쿼리 이용
GETproduct/search/[name]검색목록함수 이용

review

모델 : score(별점), contents(내용)

메소드URL설명데이터
GETreview/목록X
POSTreview/생성Review 모델
GETreview/[id]/조회X
PATCHreview/[id]/수정Review 모델
DELETEreview/[id]삭제X

0개의 댓글