如何使用DRF Serializer实现指定API结构及功能?
使用DRF实现指定API结构的Serializer与视图方案
作为Django新手,你要实现的这个API结构其实可以通过嵌套Serializer来搞定,同时结合DRF的权限和视图类来完成需求。下面一步步来拆解实现:
一、编写Serializer类
我们需要三个Serializer分别处理用户信息、关联产品(含购买日期),以及最终整合整个响应结构的主Serializer:
1. 用户信息Serializer(只读)
因为user字段是只读的,只需要返回username和email:
from rest_framework import serializers from django.contrib.auth.models import User from .models import Product, UserHistory class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['username', 'email'] read_only_fields = ['username', 'email']
2. 包含购买日期的产品Serializer
这里要从UserHistory模型获取date_bought,同时关联Product的字段,所以基于UserHistory来编写:
class ProductWithHistorySerializer(serializers.ModelSerializer): # 映射Product模型的字段到你需要的返回字段名 id = serializers.IntegerField(source='product.id') product_name = serializers.CharField(source='product.product_name') type = serializers.CharField(source='product.product_type') # 对应model里的product_type字段 image = serializers.ImageField(source='product.image') # 直接使用UserHistory的购买日期 date_bought = serializers.DateTimeField() class Meta: model = UserHistory fields = ['id', 'product_name', 'type', 'date_bought', 'image']
如果你只需要返回日期(不带时间),可以把
date_bought字段改成:date_bought = serializers.DateField(source='date_bought.date')
3. 主响应结构Serializer
这个Serializer用来整合用户信息和产品列表,同时处理添加产品的逻辑:
class UserProductHistorySerializer(serializers.Serializer): user = UserInfoSerializer(read_only=True) product = ProductWithHistorySerializer(many=True, read_only=True) # 处理POST请求添加产品的逻辑 def create(self, validated_data): # 自动获取当前认证用户,无需前端传入 user = self.context['request'].user product_id = validated_data.get('product_id') try: product = Product.objects.get(id=product_id) except Product.DoesNotExist: raise serializers.ValidationError("指定产品不存在") # 创建用户购买记录 return UserHistory.objects.create(user=user, product=product)
POST请求时,前端只需传递product_id参数即可,user由系统自动填充当前登录用户。
二、编写视图类
接下来编写视图处理GET和POST请求,同时添加权限控制:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.permissions import IsAuthenticated from rest_framework import status class UserProductHistoryView(APIView): permission_classes = [IsAuthenticated] # 仅认证用户可访问 def get(self, request): # 获取当前用户的所有购买记录 user_history = UserHistory.objects.filter(user=request.user) # 构造响应数据结构 serializer = UserProductHistorySerializer({ 'user': request.user, 'product': user_history }) return Response(serializer.data) def post(self, request): # 处理添加产品的请求 serializer = UserProductHistorySerializer( data=request.data, context={'request': request} ) if serializer.is_valid(): serializer.save() # 返回创建成功的响应 return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
三、关键细节补充
- 权限控制:通过
permission_classes = [IsAuthenticated]确保只有登录用户才能访问API,符合你“仅认证用户可执行添加操作”的需求。 - 图片URL处理:DRF默认返回图片相对路径,若要返回完整URL,需在
settings.py配置媒体文件路径:
并在项目根MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media'urls.py添加媒体路由:from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 你的其他路由 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - POST请求参数:前端发送POST请求时,只需传递
product_id,示例参数:{ "product_id": 1 }
四、路由配置
最后在你的应用urls.py中添加视图路由:
from django.urls import path from .views import UserProductHistoryView urlpatterns = [ path('user-product-history/', UserProductHistoryView.as_view(), name='user-product-history'), ]
现在你可以通过/user-product-history/端点访问API:GET请求返回你需要的结构,POST请求添加用户的购买记录。
内容的提问来源于stack exchange,提问作者Robins
相关产品推荐
相关产品推荐

