[Django/DRF - 프론트엔드와 연결하기]

SooYeon Yeon·2022년 7월 2일
0

Django

목록 보기
20/20

프론트 엔드 코드와 연결하기

깃허브에서 zip 다운, 압축풀기

node js 설치 후 cmd에서 node -v 로 확인

cmd

  • cd C:\Users\user\Downloads\17-1st-SweetHome-frontend-master\17-1st-SweetHome-frontend-master
  • npm install
  • npm start

src → config.js 파일 열어 SERVER, CARTSERVER 우리 장고 서버 127.0.0.1로 바꿈

상품이랑 리뷰 관계 맺기

model에 product 추가 후 migrate

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
# Create your models here.
from rest_framework.authtoken.admin import User

from product.models import Product

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)
    writer = models.ForeignKey(User, on_delete=models.CASCADE)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

그 모델에 있냐 기준으로 코드가 달라짐(prefetcch랑 selected처럼)

1:N 관계일때

forigen key를 N측에 넣었었음

1측을 기준으로 N측을 같이 조회

  • 상품,리뷰

N측을 기준으로 1측을 같이 조회

자동으로 serializer가 prefetch 명령어를 수행한다

from rest_framework import serializers

from product.models import Product
from review.serializer import ReviewSerializer

# 상품등록할때 리뷰는 등록안해도 되게 읽기전용으로
class ProductSerializer(serializers.ModelSerializer):
    review_set = ReviewSerializer(many=True, read_only=True) # 리뷰 여러개 달릴 수 있음
    class Meta:
        model = Product
        fields = ['name','description','price','review_set']

serializer를 여러개 둘 수도 있음

리뷰달때 상품 선택할 수 있음. 리뷰 여러개 등록해서 상품 조회해보면 리뷰 같이 볼 수 있음

내가 몇번 상품의 리뷰다 라는걸 전달해줘야함

?로 하는거 - 쿼리

경로상으로 하는 방식 (url)

json타입에 써서 보내는 방식

review_set_coount 추가해서 썸네일에 숫자 보이게하려면 product serializer 추가

from rest_framework import serializers

from product.models import Product
from review.serializer import ReviewSerializer

# 상품등록할때 리뷰는 등록안해도 되게 읽기전용으로
class ProductSerializer(serializers.ModelSerializer):
    review_set = ReviewSerializer(many=True, read_only=True) # 리뷰 여러개 달릴 수 있음
    review_set_count = serializers.IntegerField(source='review_set.count', read_only=True) # count 보여주는거 만들음
    class Meta:
        model = Product
        fields = ['name','description','price','review_set', 'review_set_coount']

주문과 관계

order 앱추가 모델만들기

order models.py

from django.db import models

# Create your models here.
from rest_framework.authtoken.admin import User

from product.models import Product

class Order(models.Model):
    product = models.ForeignKey(Product, on_delete=models.CASCADE)# 상품과 관계맺기
    user = models.ForeignKey(User,on_delete=models.CASCADE)#유저와 관계맺기

order serializer 만들기

from rest_framework import serializers

from order.models import Order

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

order views

from django.shortcuts import render

# Create your views here.
from rest_framework import viewsets

from order.models import Order
from order.serializer import OrderSerializer

class OrderViewSet(viewsets.ModelViewSet):
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

order urls

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

import order.views

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

config urls

path('', include('order.urls')),

관리자페이지 등록 후 order 몇개 등록해놓기

주문을 기준으로 사용자나 상품 뽑아낼것임

상품1 N주문 M 1사용자

주문이라는 애 기준으로 1측(사용자), 1측(상품)을 뽑아내는 것임(prefetch가 아니라 selected인)

이걸 여기서 하려면

from rest_framework import serializers
from rest_framework.authtoken.admin import User

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

class OrderProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'price', 'seller'] # 이 3개만 출력하는 Serializer를 만들음

class OrderUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', ] # 뽑아내고싶은거만 serializer를 만들어줌
class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'

    def to_representation(self, instance): # instance에는 조회하고싶은 것. product user 둘다 order에 있으니까 (정방향조회)
        response = super().to_representation(instance) #상속받은 원래 representaion객체 (숫자만 띵 써있던)
        response['product'] = OrderProductSerializer(instance.product).data #모델 안에 들어있는 product를 전달해서 원하는것(serializer에 지정해놓은것)만 뽑아줌
        response['user'] = OrderUserSerializer(instance.user).data # 유저는 원래 시리얼라이저 생성안해놨어서 위에다가 만들기
        return response

주문 조회

  • 로그인 되어있어야함
  • 자기 자신의 주문 정보(목록, 주문상세)만 조회할 수 있어야함
from django.shortcuts import render

# Create your views here.
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

from order.models import Order
from order.serializer import OrderSerializer

class OrderViewSet(viewsets.ModelViewSet):
    permission_classes = [IsAuthenticated]
    queryset = Order.objects.all()
    serializer_class = OrderSerializer

    def get_queryset(self):
        qs = super().get_queryset() # 부모 거 그대로 가져온 것
        qs = qs.filter(user=self.request.user)
        return qs

프론트엔드와 연동하기

프론트에서의 product_detail json과 형식 같게 맞추어주기

모델 수정

from django.db import models

# Create your models here.
from rest_framework.authtoken.admin import User

class Product(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField()
    price = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    seller = models.ForeignKey(User, on_delete=models.CASCADE)

    discount_percentage = models.IntegerField()
    is_free_delivery = models.BooleanField()
    is_on_sale = models.BooleanField()

class ProductImage(models.Model):
    image = models.ImageField(upload_to='images/product/', blank=True)
    product = models.ForeignKey(Product, on_delete=models.CASCADE)

serializer

from rest_framework import serializers

from product.models import Product, ProductImage
from review.serializer import ReviewSerializer

# 이미지 가져오기 위한 serializer 만들기
class ProductImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProductImage
        fields = ['image',]

# 상품등록할때 리뷰는 등록안해도 되게 읽기전용으로
class ProductSerializer(serializers.ModelSerializer):
    review_set = ReviewSerializer(many=True, read_only=True) # 리뷰 여러개 달릴 수 있음
    review_count = serializers.IntegerField(source='review_set.count', read_only=True) # count 보여주는거 만들음
    productimage_set = ProductImageSerializer(many=True, read_only=False)
    class Meta:
        model = Product
        fields = ['id','name', 'review_count','review_set','discount_percentage','is_free_delivery','is_on_sale',]

    # 재정의해서 출력을 다르게 해줄것임
    def to_representation(self, instance):
        response = super().to_representation(instance)
        response['company'] = instance.seller.username #우리는 seller였는데 저기서는 이름이 company였으니까 이렇게 지정해줌
        response['image'] = response['productimage_set'][0]['image'] #이미지 중 첫번째의 이미지
        # 할인 가격 = 원래가격 * (100-할인율) // 100
        response['discount_price'] = instance.price * (100-instance.discount_percentage) // 100

        # review 평균 계산
        if response['review_count']!=0:
            total = 0
            for review in instance.review_set.all():
                total += review.score
            response['rate_average'] = round(total // response['review_count'],1) # 1자리까지 올림
        else :
            response['rate_average'] = 0

        return response

/product/

요청받는곳, 주는 곳이 다르면 cross origin error가 생김

CORS 설정을 추가해줘야함

pip install django-cors-headers

settings,py INSTALLED_APP에 추가

'corsheaders',

settings.py MIDDLEWARE에 추가

'corsheaders.middleware.CorsMiddleware',
CORS_ORIGIN_WHITELIST = ['http://127.0.0.1:3000','http://localhost:3000'] # 이 안에 해당하는건 허용, 배포 시에는 바꿔줘야함. 도메인 같은 게 들어가는것
CORS_ALLOW_CREDENTIALS = True

0개의 댓글