如何验证GET、POST请求参数?含Django视图与序列化器场景
Django REST Framework:验证GET与POST请求参数的方案
针对你给出的TransactionViewSet和TransactionSerializer代码,我来分别说说怎么处理GET和POST请求的参数验证:
一、GET请求参数验证(以date参数为例)
GET请求的参数(比如date=2019-11-05)通常用来过滤查询集,这里有两种实用的验证方式:
方法1:用django-filter做规范验证与过滤
这是DRF里最常用的方案,先安装依赖:
pip install django-filter
然后在settings.py中注册应用和配置过滤后端:
INSTALLED_APPS = [ # ...其他已有应用 'django_filters', ] REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': [ 'django_filters.rest_framework.DjangoFilterBackend', ] }
接下来定义过滤类,同时完成date参数的格式验证:
from django_filters import rest_framework as filters from django.core.exceptions import ValidationError from django.utils.dateparse import parse_date class TransactionFilter(filters.FilterSet): date = filters.CharFilter(method='filter_by_date') def filter_by_date(self, queryset, name, value): # 验证日期格式是否合法 parsed_date = parse_date(value) if not parsed_date: raise ValidationError("日期格式错误,请使用YYYY-MM-DD格式") # 假设Transaction模型用created_at存储时间,按日期过滤 return queryset.filter(created_at__date=parsed_date) class Meta: model = Transaction fields = ['date'] class TransactionViewSet(viewsets.ModelViewSet): queryset = Transaction.objects.all() serializer_class = TransactionSerializer pagination_class = LimitOffsetPagination filterset_class = TransactionFilter
当请求的date格式错误时,DRF会自动返回400错误和对应的提示信息。
方法2:自定义get_queryset手动验证
如果不想用第三方库,也可以直接在视图里处理:
from django.core.exceptions import ValidationError from django.utils.dateparse import parse_date class TransactionViewSet(viewsets.ModelViewSet): queryset = Transaction.objects.all() serializer_class = TransactionSerializer pagination_class = LimitOffsetPagination def get_queryset(self): queryset = super().get_queryset() date_param = self.request.query_params.get('date') if date_param: parsed_date = parse_date(date_param) if not parsed_date: raise ValidationError("日期格式错误,需为YYYY-MM-DD格式") queryset = queryset.filter(created_at__date=parsed_date) return queryset
二、POST请求参数验证
POST请求的参数验证主要靠序列化器处理,针对你的代码可以这么优化:
1. 基础字段与全局逻辑验证
建议把TransactionSerializer改成继承ModelSerializer(更贴合模型逻辑),然后添加字段级和全局级的验证:
from rest_framework import serializers from .models import Transaction class TransactionSerializer(serializers.ModelSerializer): transfers = TransferSerializer(many=True) partner_transaction = PartnerTransactionDataSerializer(many=True) purchase_transaction = PurchaseTransactionDataSerializer(many=True) class Meta: model = Transaction fields = ('created_at', 'transaction_type_id', 'transfers', 'partner_transaction', 'purchase_transaction') # 验证transaction_type_id是否存在 def validate_transaction_type_id(self, value): from .models import TransactionType if not TransactionType.objects.filter(id=value).exists(): raise serializers.ValidationError("无效的交易类型ID") return value # 验证字段间的逻辑关系 def validate(self, data): transaction_type = data.get('transaction_type_id') if transaction_type == 1 and not data.get('transfers'): raise serializers.ValidationError("转账类交易必须包含transfers数据") elif transaction_type == 2 and not data.get('partner_transaction'): raise serializers.ValidationError("合作伙伴交易必须包含partner_transaction数据") return data
当POST参数不符合规则时,序列化器会自动返回400错误和对应的提示。
2. 嵌套序列化器的验证
你的嵌套序列化器(比如TransferSerializer)也需要单独实现验证逻辑,确保嵌套数据的合法性:
class TransferSerializer(serializers.ModelSerializer): class Meta: model = Transfer fields = ('amount', 'account_id') def validate_amount(self, value): if value <= 0: raise serializers.ValidationError("转账金额必须大于0") return value
嵌套序列化器的验证会在父序列化器执行验证时自动触发。
额外提示
如果需要更复杂的验证逻辑(比如日期范围、多参数组合校验),可以在视图的list(处理GET)或create(处理POST)方法里自定义逻辑,手动捕获错误并返回响应;DRF的ValidationError会自动被处理成HTTP 400 Bad Request响应,无需手动构造Response。
内容的提问来源于stack exchange,提问作者Dmitry Rusanov
相关产品推荐
相关产品推荐

