在自定义 ModelViewSet
中,你可以通过重写 get_queryset
或 perform_create
等方法来处理不同的 HTTP 请求方法(GET
, POST
等),并获取请求参数。Django REST Framework (DRF) 提供了多种方式来根据不同的 HTTP 请求类型区分处理逻辑。以下是一些常见的场景和如何实现的示例。
1. 区分 GET 和 POST 请求
在 ModelViewSet
中,GET
和 POST
请求分别对应不同的方法:
GET
请求一般由list
(列出所有对象)或retrieve
(获取单个对象)方法处理。POST
请求通常由create
方法处理。
你可以通过重写这些方法来定制每种请求的行为,并在其中获取请求参数。
示例:自定义 ModelViewSet
,区分 GET 和 POST 请求
from rest_framework import viewsets
from rest_framework.response import Response
from .models import Product
from .serializers import ProductSerializer
from rest_framework import status
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_queryset(self):
"""
根据 GET 请求的查询参数来自定义查询集
"""
queryset = super().get_queryset()
# 获取 GET 请求参数,例如 'category' 或 'price_range'
category = self.request.query_params.get('category', None)
price_range = self.request.query_params.get('price_range', None)
if category:
queryset = queryset.filter(category=category)
if price_range:
min_price, max_price = price_range.split(',')
queryset = queryset.filter(price__gte=min_price, price__lte=max_price)
return queryset
def create(self, request, *args, **kwargs):
"""
根据 POST 请求的参数创建新产品
"""
# 获取 POST 请求的参数
name = request.data.get('name')
category = request.data.get('category')
price = request.data.get('price')
# 执行自定义的创建逻辑
product = Product.objects.create(name=name, category=category, price=price)
# 使用序列化器来返回响应
serializer = self.get_serializer(product)
return Response(serializer.data, status=status.HTTP_201_CREATED)
关键点:
-
get_queryset()
:用于处理GET
请求中的查询参数。通过self.request.query_params.get('param_name')
来获取查询字符串中的参数,之后可以基于这些参数过滤数据库查询。 -
create()
:用于处理POST
请求。request.data
包含了请求体中的数据,你可以通过request.data.get('param_name')
来获取相应的字段值。
2. 获取查询参数和请求体参数
request.query_params
:用于获取 URL 中的查询参数(例如?key=value
)。request.data
:用于获取 POST 请求的请求体中的数据。
示例:根据不同的请求处理逻辑
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_queryset(self):
queryset = super().get_queryset()
# GET 请求的查询参数
name = self.request.query_params.get('name', None)
min_price = self.request.query_params.get('min_price', None)
max_price = self.request.query_params.get('max_price', None)
if name:
queryset = queryset.filter(name__icontains=name)
if min_price and max_price:
queryset = queryset.filter(price__gte=min_price, price__lte=max_price)
return queryset
def create(self, request, *args, **kwargs):
# POST 请求的请求体数据
name = request.data.get('name')
category = request.data.get('category')
price = request.data.get('price')
if not name or not category or not price:
return Response({'error': 'Missing required fields'}, status=status.HTTP_400_BAD_REQUEST)
product = Product.objects.create(name=name, category=category, price=price)
serializer = self.get_serializer(product)
return Response(serializer.data, status=status.HTTP_201_CREATED)
3. 如何处理 PUT 和 PATCH 请求
PUT
和 PATCH
请求通常用于更新已有的资源,ModelViewSet
会默认提供 update
和 partial_update
方法。在这两种方法中,你也可以通过 request.data
获取传入的更新数据,并自定义更新逻辑。
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def update(self, request, *args, **kwargs):
"""
处理 PUT 请求,更新整个资源
"""
instance = self.get_object()
instance.name = request.data.get('name', instance.name)
instance.category = request.data.get('category', instance.category)
instance.price = request.data.get('price', instance.price)
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
def partial_update(self, request, *args, **kwargs):
"""
处理 PATCH 请求,部分更新资源
"""
instance = self.get_object()
instance.name = request.data.get('name', instance.name)
instance.category = request.data.get('category', instance.category)
instance.price = request.data.get('price', instance.price)
instance.save()
serializer = self.get_serializer(instance)
return Response(serializer.data)
4. 访问其他请求信息(如请求头、用户信息等)
你可以在视图中直接访问请求的其他信息,如请求头、用户信息、认证信息等:
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def create(self, request, *args, **kwargs):
user = request.user # 获取当前请求的用户
user_agent = request.headers.get('User-Agent') # 获取请求头中的 User-Agent
# 进行自定义逻辑,例如记录用户的活动
print(f"User {user.username} is creating a new product with User-Agent: {user_agent}")
# 创建产品
product = Product.objects.create(
name=request.data.get('name'),
category=request.data.get('category'),
price=request.data.get('price')
)
# 返回响应
serializer = self.get_serializer(product)
return Response(serializer.data, status=status.HTTP_201_CREATED)
总结
get_queryset()
用于处理GET
请求,获取查询参数。create()
用于处理POST
请求,获取请求体数据。update()
和partial_update()
用于处理PUT
和PATCH
请求,获取请求体数据并更新对象。- 使用
self.request.query_params
获取查询参数(GET
请求); - 使用
self.request.data
获取请求体数据(POST
,PUT
,PATCH
请求); - 你可以根据请求方法和请求数据灵活处理不同的逻辑。