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 視圖。