Chuyển đến nội dung chính

第 5 課:DRF 序列化器和視圖

DRF 設定、序列化器(序列化器、模型序列化器、巢狀序列化器)。 APIView、GenericAPIView、mixins。請求/回應對象、狀態代碼、內容協商。

💻 程式設計 — 第 5 課 第 5 課:DRF 序列化器和視圖

Django:從基礎到高級

第 2 部分:Django REST 框架

亞洲開發網

1.安裝DRF

pip install djangorestframework
# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
]

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 20,
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ],
}

2. 序列化器

from rest_framework import serializers
from .models import Product, Category

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ['id', 'name', 'slug']

class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)
    category_id = serializers.PrimaryKeyRelatedField(
        queryset=Category.objects.all(),
        source='category',
        write_only=True,
    )

    class Meta:
        model = Product
        fields = ['id', 'name', 'slug', 'description', 'price',
                  'category', 'category_id', 'created_at']
        read_only_fields = ['id', 'created_at']

    def validate_price(self, value):
        if value <= 0:
            raise serializers.ValidationError('Giá phải lớn hơn 0')
        return value

嵌套序列化器(可寫入)

class OrderItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = ['product', 'quantity', 'price']

class OrderSerializer(serializers.ModelSerializer):
    items = OrderItemSerializer(many=True)

    class Meta:
        model = Order
        fields = ['id', 'customer', 'items', 'total', 'created_at']

    def create(self, validated_data):
        items_data = validated_data.pop('items')
        order = Order.objects.create(**validated_data)
        for item_data in items_data:
            OrderItem.objects.create(order=order, **item_data)
        return order

3.API視圖

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class ProductListAPI(APIView):
    def get(self, request):
        products = Product.objects.filter(is_active=True)
        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = ProductSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

4.GenericAPIView 和 Mixins

from rest_framework.generics import (
    ListCreateAPIView,
    RetrieveUpdateDestroyAPIView,
)

class ProductListCreateAPI(ListCreateAPIView):
    queryset = Product.objects.filter(is_active=True)
    serializer_class = ProductSerializer

    def get_queryset(self):
        qs = super().get_queryset()
        category = self.request.query_params.get('category')
        if category:
            qs = qs.filter(category__slug=category)
        return qs

class ProductDetailAPI(RetrieveUpdateDestroyAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    lookup_field = 'slug'

5. 網址配置

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('api/products/', views.ProductListCreateAPI.as_view()),
    path('api/products/<slug:slug>/', views.ProductDetailAPI.as_view()),
]

下一篇: 視圖集、路由器和分頁 — 優化的 API 視圖。