浙江省住房与城乡建设部网站,做网站国家大学科技园郑州,网站没快照,网站建设与维护试卷Resquests#xff08;请求#xff09;
属性
.data
request.data 返回请求正文的解析内容。它包括所有解析的内容, 包括 文件或非文件 输入。 它支持解析除POST之外的HTTP方法的内容#xff0c;这意味着你可以访问PUT和PATCH请求的内容。 它支持REST framework灵活的请求解…Resquests请求
属性
.data
request.data 返回请求正文的解析内容。它包括所有解析的内容, 包括 文件或非文件 输入。 它支持解析除POST之外的HTTP方法的内容这意味着你可以访问PUT和PATCH请求的内容。 它支持REST framework灵活的请求解析而不仅仅支持表单数据。 例如你可以以与处理传入表单数据相同的方式处理传入的JSON数据。
.query_params
request.query_params是request.GET的一个更准确的同义词。
为了让你的代码清晰明了, 我们建议使用 request.query_params 而不是Django标准的request.GET。这样做有助于保持代码库更加正确和明了——因为任何HTTP方法类型可能包括查询参数而不仅仅是GET请求。
Response响应
Response 类使用的渲染器无法自行处理像 Django model 实例这样的复杂数据类型因此你需要在创建 Response 对象之前将数据序列化为基本数据类型。你可以使用 REST framework的 Serializer 类来执行此类数据的序列化或者使用你自定义的来序列化
签名:
Response(data, statusNone, template_nameNone, headersNone, content_typeNone)
参数:
data: response的数列化数据.
status: response的状态码。默认是200. 另行参阅 status codes.
template_name: HTMLRenderer 选择要使用的模板名称。
headers: A dictionary of HTTP headers to use in the response.
content_type: response的内容类型。通常由渲染器自行设置由content negotiation确定但是在某些情况下你需要明确指定内容类型。
属性
.data Request 对象的未渲染内容。
.status_code HTTP 响应的数字状态吗。
.content response的呈现内容。 .render() 方法必须先调用才能访问 .content 。
类视图
APIView
APIView是DRF中的基本视图类它继承自Django的View类并添加了一些针对API设计的功能例如请求解析、内容协商、认证和权限控制等。 它可以返回REST framework的Response而不是Django的HttpRequest。视图会管理内容协议给响应设置正确的渲染器。 当你使用APIView时需要为每个HTTP方法如GET、POST、PUT、DELETE等定义一个单独的处理方法如get()、post()、put()、delete()等。APIView适用于处理较为复杂的业务逻辑或者需要自定义处理方法的场景。
ViewSet
ViewSet是DRF中的一个更高级别的视图抽象它继承自APIView。 ViewSet将视图的操作方法如list、create、retrieve、update、destroy等与HTTP方法解耦这意味着你可以在一个ViewSet中定义多个操作方法并通过路由器Routers自动将这些操作方法映射到对应的HTTP方法和URL。ViewSet适用于处理标准的CRUD操作可以简化视图和路由的定义。此外ViewSet还支持动作Actions允许你为ViewSet添加自定义操作方法。
ViewSet 只是一种基于类的视图它不提供任何方法处理程序如 .get()或.post(),而是提供诸如 .list() 和 .create() 之类的操作。 ViewSet 的方法处理程序仅使用 .as_view() 方法绑定到完成视图的相应操作。
自带视图
def list(self, request):passdef create(self, request):passdef retrieve(self, request, pkNone):pass其中retrieve是ViewSet中预定义的一个方法它用于处理获取单个资源的请求。当你发送一个GET请求到一个具体的资源URL时
例如/api/items/1/ViewSet会调用retrieve方法来处理这个请求。retrieve方法通常会接收两个参数self和pk主键。它会根据pk从数据库中获取对应的资源实例然后返回这个实例。
如果找不到对应的资源retrieve方法会返回一个404错误。def update(self, request, pkNone):passdef partial_update(self, request, pkNone):passdef destroy(self, request, pkNone):pass指定序列化器和查询集
在ViewSet中需要指定序列化器和查询集。
# 定义了视图集将操作的基础查询集
queryset User.objects.all()
# 序列化器它定义了如何将User模型的实例转换为JSON格式以及如何将JSON数据转换回User模型的实例。
serializer UserSerializer(queryset, manyTrue)路由注册
我们会用一个router来注册我们的viewset让urlconf自动生成。
from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouterrouter DefaultRouter()
router.register(rusers, UserViewSet)
urlpatterns router.urls案例
from django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializerclass UserViewSet(viewsets.ModelViewSet):一个提供标准动作的 viewsetqueryset User.objects.all()serializer_class UserSerializerdetail_route(methods[post])def set_password(self, request, pkNone):user self.get_object()serializer PasswordSerializer(datarequest.data)if serializer.is_valid():user.set_password(serializer.data[password])user.save()return Response({status: password set})else:return Response(serializer.errors,statusstatus.HTTP_400_BAD_REQUEST)list_route()def recent_users(self, request):recent_users User.objects.all().order(-last_login)page self.paginate_queryset(recent_users)if page is not None:serializer self.get_serializer(page, manyTrue)return self.get_paginated_response(serializer.data)serializer self.get_serializer(recent_users, manyTrue)return Response(serializer.data)拓展format
在ViewSet中每个操作方法如list、create、retrieve等都可以包含一个formatNone的关键字参数。这个参数的默认值是None表示视图将根据客户端请求的Accept头部自动选择合适的数据格式。如果你的API需要支持格式后缀那么务必在每个操作方法中包含这个参数。
例如以下请求将返回JSON格式的数据
GET /api/items/1.json 而以下请求将返回XML格式的数据
GET /api/items/1.xml 当你在ViewSet中定义操作方法时可以根据需要处理format参数。但通常情况下Django REST framework会自动处理内容协商和序列化你不需要在操作方法中显式处理这个参数。
拓展固定视图
如果我们需要我们可以将这个viewset绑定到两个单独的视图像这样
user_list UserViewSet.as_view({get: list})
user_detail UserViewSet.as_view({get: retrieve})自定义视图
如果你有需要被路由到的特别方法你可以使用 detail_route 或 list_route 装饰器将它们标记为需要路由。
detail_route 装饰器在其URL模式中包含 pk 用于需要单个实例的方法。The list_route 装饰器用于对对象列表进行操作的方法。
装饰器可以另外获取为路由视图设置的额外参数。例如…
detail_route(methods[post], permission_classes[IsAdminOrIsSelf])
def set_password(self, request, pkNone):...这些装饰器将默认路由 GET 请求但也可以通过使用 methods 参数接受其他 HTTP 方法。例如
detail_route(methods[post, delete])
def unset_password(self, request, pkNone):...这两个新动作将在 urls ^users/{pk}/set_password/$和^users/{pk}/unset_password/$上可用。
DRF中的返回的Response、HttpResponse和JsonResponse有什么区别
Response这是DRF特有的响应对象主要用于返回API请求的结果。Response对象可以自动处理多种内容类型如JSON、XML等并根据客户端请求的Accept头部选择合适的内容类型。Response对象还可以与DRF的序列化器Serializers一起使用以自动序列化和反序列化数据。此外Response对象还支持更丰富的状态码和错误处理。
HttpResponse这是Django中的一个基本响应对象用于返回HTTP响应。HttpResponse对象默认的内容类型是text/html适用于返回HTML内容。如果需要返回其他内容类型需要手动设置。HttpResponse对象通常用于处理非API的请求如网页渲染等。
JsonResponse这是Django中的一个特殊的HttpResponse对象专门用于返回JSON数据。JsonResponse对象的内容类型默认为application/json。当你需要返回JSON格式的数据时可以使用JsonResponse它会自动将Python字典或列表序列化为JSON字符串。需要注意的是JsonResponse不支持序列化Django模型实例或查询集这时需要手动序列化数据。
Router路由器
SimpleRouter
SimpleRouter是一个基础的路由器它为视图集自动生成标准的CRUD操作的URL路由。这些路由包括
列表视图listGET // 详情视图detailGET //{pk}/ 创建视图createPOST // 更新视图updatePUT //{pk}/ 部分更新视图partial_updatePATCH //{pk}/ 删除视图destroyDELETE //{pk}/ 这里的是在注册视图集时指定的URL前缀{pk}是对象的主键。
DefaultRouter更推荐
DefaultRouter继承自SimpleRouter因此它提供了SimpleRouter的所有路由同时还添加了一个默认的API根视图。这个根视图返回一个包含所有列表视图的超链接的响应通常用于API的入口点。
Renderer渲染器
渲染器Renderer是Django REST framework中用于将数据转换为特定格式的组件。渲染器的作用是将服务器返回的原始数据如Python字典、列表等序列化为客户端可以接收的格式如JSON、XML等。渲染器会根据客户端请求的Accept头部或URL中的格式后缀自动选择合适的内容类型。
Django REST framework内置了多种渲染器如JSONRenderer、XMLRenderer、HTMLRenderer等。你可以在项目设置中通过REST_FRAMEWORK设置来配置默认的渲染器也可以在视图中通过renderer_classes属性来为特定视图指定渲染器。例如
python 复制代码
REST_FRAMEWORK { ‘DEFAULT_RENDERER_CLASSES’: [ ‘rest_framework.renderers.JSONRenderer’, ‘rest_framework.renderers.XMLRenderer’, ], } 在Response对象中渲染器的作用是将传入的data参数序列化为合适的格式。需要注意的是渲染器无法处理复杂的数据类型如Django模型实例。在这种情况下你需要使用序列化器Serializer先将数据序列化为基本数据类型如字典、列表等然后再创建Response对象。
例如你可以使用Django REST framework的序列化器将模型实例序列化为字典
python 复制代码
from rest_framework import serializers from rest_framework.response import Response
class UserSerializer(serializers.ModelSerializer): class Meta: model User fields ‘all’
user User.objects.get(pk1) serialized_user UserSerializer(user).data return Response(serialized_user) 总之渲染器是Django REST framework中用于将数据转换为特定格式的组件它负责将视图返回的数据序列化为客户端可以接收的格式。在使用Response对象时需要确保传入的数据已经序列化为基本数据类型。
Serializers序列化器
序列化器的主要功能包括
序列化将模型实例或其他数据转换为Python字典然后可以被渲染成JSON或其他格式。反序列化将传入的数据如JSON解析为Python数据类型进行验证并创建或更新模型实例。验证提供数据验证逻辑确保传入的数据符合预期格式和规则。
假设你有一个Django模型User你想要创建一个序列化器来处理用户数据的序列化和反序列化。 首先定义你的模型如果还没有定义
from django.db import modelsclass User(models.Model):username models.CharField(max_length100)email models.EmailField()is_active models.BooleanField(defaultTrue)然后创建一个序列化器
from rest_framework import serializers
from .models import Userclass UserSerializer(serializers.ModelSerializer):class Meta:model Userfields [id, username, email, is_active]在这个UserSerializer中我们继承了serializers.ModelSerializer这是一个快捷的序列化器它自动根据模型字段生成序列化器字段。在Meta类中我们指定了要包含在序列化中的模型和字段。
序列化对象
现在你可以在视图中使用这个序列化器来序列化用户数据
from django.http import JsonResponse
from .models import User
from .serializers import UserSerializerdef user_list(request):users User.objects.all()serializer UserSerializer(users, manyTrue)return JsonResponse(serializer.data, safeFalse)在这个视图中我们查询了所有的用户然后使用UserSerializer来序列化这些用户数据。manyTrue参数告诉序列化器我们正在序列化一个对象列表而不是单个对象。最后我们将序列化后的数据返回为JSON响应。
反序列化对象
同样如果你想要反序列化传入的数据并创建一个新的用户实例你可以这样做
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
from rest_framework.parsers import JSONParser
from .models import User
from .serializers import UserSerializercsrf_exempt
def user_create(request):if request.method POST:data JSONParser().parse(request)serializer UserSerializer(datadata)if serializer.is_valid():serializer.save()return JsonResponse(serializer.data, status201)return JsonResponse(serializer.errors, status400)在这个视图中我们首先解析了传入的JSON数据然后使用UserSerializer来反序列化数据。我们检查数据是否有效如果有效我们保存新的用户实例并返回新创建的用户数据。如果数据无效我们返回一个包含错误信息的JSON响应。
注意反序列化多个对象默认支持多个对象的创建但是不支持多个对象的更新。
利用序列化器创建相应对象
如果我们希望能够返回基于验证数据的完整对象实例我们需要实现其中一个或全部实现.create()和update()方法。例如
class CommentSerializer(serializers.Serializer):email serializers.EmailField()content serializers.CharField(max_length200)created serializers.DateTimeField()def create(self, validated_data):return Comment(**validated_data)def update(self, instance, validated_data):instance.email validated_data.get(email, instance.email)instance.content validated_data.get(content, instance.content)instance.created validated_data.get(created, instance.created)return instance然后再调用.save()方法即可创建一个数据验证过的对象实例。
comment serializer.save()注意如果只实现了create方法那么每次创建一个对象都是不同的地址。
如果只实现了update()方法那么在调用serializer.save()方法时将会更新现有的Comment对象而不是创建新的对象。所以在调用serializer.save()方法时如果没有传递实例参数instance将会引发一个TypeError异常。因为在没有实例参数的情况下无法确定要更新哪个对象。
保存到数据库里
我们如果想要的话可以在外部将用.save创建的对象保存到数据库这称为手动保存。
serializer CommentSerializer(datarequest.data)
if serializer.is_valid():comment serializer.save()Comment.objects.create(comment)但是我们也可以在create和update方法里就确保这些对象会保存到数据库里。这称为自动保存。
def create(self, validated_data):return Comment.objects.create(**validated_data)def update(self, instance, validated_data):instance.email validated_data.get(email, instance.email)instance.content validated_data.get(content, instance.content)instance.created validated_data.get(created, instance.created)instance.save()return instance创建实例时注入其他属性数据
直接在.save()时添加其他关键字参数就可 serializer.save(ownerrequest.user)
验证
is_valid
反序列化数据的时候你始终需要先调用is_valid()方法然后再尝试去访问经过验证的数据或保存对象实例。.is_valid()方法使用可选的raise_exception标志如果存在验证错误将会抛出一个serializers.ValidationError异常。这些异常由REST framework提供的默认异常处理程序自动处理默认情况下将返回HTTP 400 Bad Request响应。
意思就是
serializer.is_valid()默认情况下当调用serializer.is_valid()方法时如果数据验证失败它将返回一个布尔值False并将错误信息存储在serializer.errors属性中。您可以通过检查serializer.errors来获取验证错误的详细信息。serializer.is_valid(raise_exceptionTrue)当您将raise_exception参数设置为True时如果数据验证失败它将引发一个ValidationError异常。这意味着您可以使用异常处理机制来处理验证错误而不需要手动检查serializer.errors。
is_valid()方法底层会依次执行以下步骤
调用run_validation()方法该方法会对输入数据进行验证并返回验证后的数据。调用validate()方法该方法会在验证通过后执行自定义的验证逻辑。如果验证通过is_valid()方法返回True否则返回False。
run_validation
run_validation()方法会尝试在以下情况下进行类型转换 字符串类型转换为其他类型当字段声明为IntegerField、FloatField、DecimalField、BooleanField等数值类型时如果输入数据是字符串类型run_validation()方法会尝试将其转换为相应的数值类型。 数值类型转换为字符串类型当字段声明为CharField、EmailField、URLField等字符串类型时如果输入数据是数值类型run_validation()方法会尝试将其转换为字符串类型。 字符串类型转换为日期/时间类型当字段声明为DateField、DateTimeField等日期/时间类型时如果输入数据是字符串类型run_validation()方法会尝试将其转换为相应的日期/时间类型。
validate()重写以达到自定义验证方法
示例
from rest_framework import serializersclass EventSerializer(serializers.Serializer):description serializers.CharField(max_length100)start serializers.DateTimeField()finish serializers.DateTimeField()def validate(self, data):Check that the start is before the stop.if data[start] data[finish]:raise serializers.ValidationError(finish must occur after start)return data自定义某个字段的验证方法
自定义的validate_field_name方法应该返回一个验证过的数据或者抛出一个serializers.ValidationError异常。 当然如果在序列化器中声明field_name的时候带有requiredFalse参数字段不被包含的时候这个验证步骤就不会执行。
from rest_framework import serializersclass BlogPostSerializer(serializers.Serializer):title serializers.CharField(max_length100)content serializers.CharField()def validate_title(self, value):Check that the blog post is about Django.if django not in value.lower():raise serializers.ValidationError(Blog post is not about Django)return value在多个序列化器中重复使用相同的验证器
共享验证器实例
在这个例子中我们定义了一个UniqueRoomBookingValidator类它接受一个查询集、日期字段和房间字段作为参数。在它的__call__方法中它检查是否存在与给定日期和房间号冲突的预订。如果存在冲突它将引发一个ValidationError。
然后我们创建了一个common_room_booking_validator实例并在三个不同的序列化器中重用它EventSerializer、AppointmentSerializer和ReservationSerializer。这样无论是处理事件、预约还是预订都会应用相同的房间预订冲突验证逻辑。
这个例子展示了如何创建一个复杂的自定义验证器并在多个序列化器中重用它以确保在不同模型和上下文中应用相同的业务规则。这种方法提高了代码的可维护性并确保了验证逻辑的一致性。
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from myapp.models import Event, Appointment, Reservationclass UniqueRoomBookingValidator:def __init__(self, queryset, date_field, room_field):self.queryset querysetself.date_field date_fieldself.room_field room_fielddef __call__(self, attrs):date attrs[self.date_field]room_number attrs[self.room_field]# 检查是否存在冲突的预订conflicting_bookings self.queryset.filter(**{self.date_field: date,self.room_field: room_number})if conflicting_bookings.exists():raise ValidationError(The room is already booked for this date.)# 创建一个通用的UniqueRoomBookingValidator实例
common_room_booking_validator UniqueRoomBookingValidator(querysetEvent.objects.all(),date_fielddate,room_fieldroom_number
)class EventSerializer(serializers.Serializer):name serializers.CharField()room_number serializers.IntegerField()date serializers.DateField()class Meta:validators [common_room_booking_validator]class AppointmentSerializer(serializers.Serializer):client_name serializers.CharField()room_number serializers.IntegerField()date serializers.DateField()class Meta:validators [common_room_booking_validator]class ReservationSerializer(serializers.Serializer):guest_name serializers.CharField()room_number serializers.IntegerField()date serializers.DateField()class Meta:validators [common_room_booking_validator]# 使用EventSerializer、AppointmentSerializer和ReservationSerializer时
# 它们都会应用相同的UniqueRoomBookingValidator验证逻辑继承一个公共序列化器类更普遍推荐
from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator
from myapp.models import Event, Appointment, Reservation# 创建一个基础序列化器类包含共享的字段和验证逻辑
class BaseRoomBookingSerializer(serializers.Serializer):room_number serializers.IntegerField()date serializers.DateField()class Meta:validators [UniqueTogetherValidator(querysetEvent.objects.all(),fields[room_number, date])]# EventSerializer继承自BaseRoomBookingSerializer并添加特定的字段
class EventSerializer(BaseRoomBookingSerializer):name serializers.CharField()# AppointmentSerializer继承自BaseRoomBookingSerializer并添加特定的字段
class AppointmentSerializer(BaseRoomBookingSerializer):client_name serializers.CharField()# ReservationSerializer继承自BaseRoomBookingSerializer并添加特定的字段
class ReservationSerializer(BaseRoomBookingSerializer):guest_name serializers.CharField()# 使用EventSerializer、AppointmentSerializer和ReservationSerializer时
# 它们都会应用相同的UniqueTogetherValidator验证逻辑处理嵌套对象默认不可写
class UserSerializer(serializers.Serializer):email serializers.EmailField()username serializers.CharField()class CommentSerializer(serializers.Serializer):user UserSerializer()content serializers.CharField()created serializers.DateTimeField(requiredTrue)错误表示
当我们尝试使用以下数据来创建一个CommentSerializer实例时
{user: {email: foobar, username: doe},content: baz
}实现.create()实现可写的嵌套表示
在Django REST frameworkDRF中“可写”writable通常指的是能够处理数据写入操作的能力例如创建POST或更新PUT/PATCH数据。当官方文档提到可写的嵌套表示时它指的是序列化器不仅能够处理数据的序列化将模型实例转换为JSON等格式还能处理反序列化将JSON等格式转换为模型实例并执行数据的保存操作。
在处理嵌套对象时DRF默认只提供了序列化的能力即它可以将嵌套的模型实例转换为嵌套的JSON表示。但是如果你想要在接收到嵌套的JSON数据时创建或更新数据库中的相关记录你需要自己实现.create()和.update()方法来处理这些嵌套的数据。 因为嵌套关系的创建和更新行为可能不明确并且可能需要关联模型间的复杂依赖关系REST framework 3 要求你始终明确的定义这些方法。默认的ModelSerializer .create()和.update()方法不包括对可写嵌套关联的支持。
官方文档中的示例展示了如何在序列化器中实现.create()方法以便能够创建具有嵌套关系的对象。在这个例子中我们有一个User模型和一个关联的Profile模型。UserSerializer包含一个嵌套的ProfileSerializer用于处理profile字段。
我们可以看到user字段中的email值不是一个有效的电子邮件地址因为它没有符号所以UserSerializer验证失败。同时CommentSerializer中的created字段是必填的但在提供的数据中缺失所以也验证失败。
调用serializer.is_valid()方法后我们得到False表示数据验证不通过。然后我们可以通过serializer.errors来查看具体的错误信息。错误信息会按照字段组织在一个字典中嵌套的user字段错误也会被嵌套在’user’键下
{user: {email: [Enter a valid e-mail address.]},created: [This field is required.]
}只验证部分传入的字段部分更新
默认情况下序列化器必须传递所有必填字段的值否则就会引发验证错误。你可以使用 partial参数来允许部分更新。
serializer CommentSerializer(comment, data{content: ufoo bar}, partialTrue)访问未处理的数据和实例
.initial_data 属性 .initial_data 属性用于访问传递给序列化器的原始输入数据通常是来自客户端的请求数据。这些数据通常是未经验证的并且是序列化器进行验证和保存操作之前的原始状态。.initial_data 仅在序列化器被实例化时传递了 data 参数时存在。 .instance 属性 .instance 属性用于访问序列化器关联的模型实例通常是从数据库中检索的对象。这个属性通常在序列化器用于更新或检索操作时使用以便访问和操作现有的数据库记录。.instance 在序列化器被实例化时传递了 instance 参数时存在如果没有传递则为 None。
举例说明
class EventDetailView(generics.RetrieveUpdateAPIView):queryset Event.objects.all()serializer_class EventSerializerdef perform_update(self, serializer):# 在这里你可以通过serializer.instance来访问原始的Event实例# 这是因为在这个上下文中你可能没有直接的引用到event_instanceoriginal_event serializer.instance# ...执行一些额外的逻辑...serializer.save()class EventCreateView(APIView):def post(self, request, *args, **kwargs):# 在这里我们直接使用request.data而不是一个单独的submitted_data变量serializer EventSerializer(datarequest.data)if serializer.is_valid():serializer.save()return Response(serializer.data, status201)return Response(serializer.errors, status400)def perform_create(self, serializer):# 假设我们需要在创建对象之前做一些额外的检查# 我们可以在这里使用.initial_data来访问原始提交的数据if some_condition in serializer.initial_data:# 执行一些额外的逻辑passserializer.save()ModelSerializer
通常你会想要与Django模型相对应的序列化类。
ModelSerializer类能够让你自动创建一个具有模型中相应字段的Serializer类。
这个ModelSerializer类和常规的Serializer类一样不同的是
它根据模型自动生成一组字段。 它自动生成序列化器的验证器比如unique_together验证器。 它默认简单实现了.create()方法和.update()方法。 声明一个ModelSerializer如下
class AccountSerializer(serializers.ModelSerializer):class Meta:model Accountfields (id, account_name, users, created)# 你还可以将fields属性设置成__all__来表明使用模型中的所有字段。你可以将exclude属性设置成一个从序列化器中排除的字段列表。例如
class AccountSerializer(serializers.ModelSerializer):class Meta:model Accountexclude (users,)拓展检查ModelSerializer
序列化类生成有用的详细表示字符串允许你全面检查其字段的状态。 这在使用ModelSerializers时特别有用因为你想确定自动创建了哪些字段和验证器。
要检查的话打开Django shell,执行 python manage.py shell然后导入序列化器类实例化它并打印对象的表示 from myapp.serializers import AccountSerializerserializer AccountSerializer()print(repr(serializer))
AccountSerializer():id IntegerField(labelID, read_onlyTrue)name CharField(allow_blankTrue, max_length100, requiredFalse)owner PrimaryKeyRelatedField(querysetUser.objects.all())
指定只读字段
你可能希望将多个字段指定为只读而不是显式的为每个字段添加read_onlyTrue属性这种情况你可以使用Meta的read_only_fields选项。
该选项应该是字段名称的列表或元祖并像下面这样声明
class AccountSerializer(serializers.ModelSerializer): class Meta: model Account fields (‘id’, ‘account_name’, ‘users’, ‘created’) read_only_fields (‘account_name’,) 模型中已经设置editableFalse的字段和默认就被设置为只读的AutoField字段都不需要添加到read_only_fields选项中。
Serializer fields序列化字段
属性
required 如果在反序列化时候没有提供这个字段通常会抛出一个错误。如果在反序列化操作中不需要这个字段将其设置为False。 将其设置为False同样允许在序列化实例时忽略对象属性或者字段的键。如果这个键不存在则该键根本不会出现在输出中。 默认是True
无论是allow_blank与allow_null上有效的选项ChoiceField但我们强烈建议您只使用一个而不是两个。allow_blank应该首选用于文本选择并且allow_null应该首选用于数字或其他非文本选择。
Pagination分页
分页API可以支持以下两者之一
作为响应内容的一部分提供的分页链接。包含在响应标头中的分页链接例如 Content-Range 或 Link。 当前内置样式都使用作为响应内容一部分的链接。当使用可浏览的API时这种样式更容易访问。
只有在使用常规视图或视图集时才自动执行分页。如果使用的是常规的 APIView 则需要自行调用分页API以确保返回分页的响应。请参见 mixins.ListModelMixin 以及 generics.GenericAPIView 类作为示例。
设置分页样式
可以使用 DEFAULT_PAGINATION_CLASS 和 PAGE_SIZE 设置键全局设置分页样式。例如
REST_FRAMEWORK {DEFAULT_PAGINATION_CLASS: rest_framework.pagination.LimitOffsetPagination,PAGE_SIZE: 100
}注意您需要同时设置分页类和应该使用的页面大小。默认情况下 DEFAULT_PAGINATION_CLASS 和 PAGE_SIZE 均为 None 。 也可以使用 pagination_class 属性在单个视图上设置分页类。 如果同时设置了全局和单个视图后者优先级更高。
PageNumberPaginationDRF自带分页样式之一
PageNumberPagination 类包含许多属性通过重写其中的一些属性可以修改分页属性
为了设置这些属性应当重写 PageNumberPagination 类然后如上所述启用自定义分页类。
django_paginator_class —— 要使用的django paginator类。默认为 django.core.paginator.Paginator 适用于大多数情况。 page_size —— 表示页面大小的数值。如果设置则覆盖 PAGE_SIZE 设置。其默认值与 PAGE_SIZE 设置键相同。 page_query_param —— 一个字符串值指示用于分页控件的查询参数的名称。 page_size_query_param —— 如果设置这是一个字符串值指示允许客户端根据每个请求设置页面大小的查询参数的名称。默认值为 None表示客户端可能无法控制请求的页面大小。 max_page_size —— 如果设置这是一个数字值指示允许的最大请求页面大小。此属性仅在设置了 page_size_query_param 时有效。
Exceptions异常
DRF自带异常处理
REST framework的视图能处理各种各样的异常能处理并返回合适的错误响应。
以下异常会被处理
在REST framework内部产生的APIException 的子类异常。原生Django的Http404 异常.原生Django的PermissionDenied 异常. 在上述各类情况中REST framework会返回一个带有合适状态码与content-type的响应。响应正文(Response body)会包含有关报错的任何额外信息。
大多数报错响应都会在响应正文里包含一个detail。
例如下面的请求
DELETE http://api.example.com/foo/bar HTTP/1.1
Accept: application/json
就可能会收到一个报错响应表示DELETE方法在该资源上不可使用。HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 42{detail: Method DELETE not allowed.}验证类的报错在处理上略有不同他们会把字段名作为keys包含在响应正文中。验证类的报错如果并不是针对特定的字段则会使用non_field_error或者是setting中NON_FIELD_ERRORS_KEY的值作为keys返回。
一个验证类错误大概是这个样子
HTTP/1.1 400 Bad Request
Content-Type: application/json
Content-Length: 94{amount: [A valid integer is required.], description: [This field may not be blank.]}自定义异常处理
自定义异常处理函数处理DRF框架相关异常
当然你也可以自己实现自定义异常处理只需要创建一个异常处理函数即可它要能够将你API views里引发的异常转换成响应对象。这样你就可以自己控制你API的报错响应的样式了。
这个函数必须接受一对参数第一个是需要处理的异常第二个则是一个字典类型这个字典需要包含一切额外相关信息比如当前正在处理的view等。异常处理函数要么返回一个Response对象要么就直接返回None(比如异常无法正常处理的情况下)。如果处理函数返回了None那么这个异常会继续向上报错并由Django返回一个标准的HTTP 500的’server error’响应。
举个例子你可能想确保你所有的响应正文里都会包含该次请求的HTTP状态码就像这样
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 62{status_code: 405, detail: Method DELETE not allowed., view: your_project.views.YourAPIView}想要变成这样的响应你可以写一个像下面这样的异常处理函数
from rest_framework.views import exception_handlerdef custom_exception_handler(exc, context):# 首先调用REST framework默认的异常处理# 以获得标准的错误响应。response exception_handler(exc, context)# 接下来将HTTP状态码加到响应中。if response is not None:response.data[status_code] response.status_code# 获取当前处理异常的view的信息view context[view]# 在响应中添加view的信息response.data[view] str(view)return response异常处理函数还必须通过settings来配置来替换DRF默认的异常处理如下
REST_FRAMEWORK {EXCEPTION_HANDLER: my_project.my_app.utils.custom_exception_handler
}如果没有特别指出EXCEPTION_HANDLER’设置默认使用REST framework提供的标准异常处理
REST_FRAMEWORK {EXCEPTION_HANDLER: rest_framework.views.exception_handler
}要注意的是异常处理只会由DRF框架产生异常的响应调用。如验证错误、权限错误、序列化错误具体点就是使用DRF自己的序列化器进行数据验证时如果数据验证失败DRF会自动将验证错误转换为一个异常并生成一个HTTP 400 Bad。
它无法处理view直接返回的响应即写在代码里的return Response(serializer.errors, statusHTTP_400_BAD_REQUEST)啥的。
自定义异常类处理视图相关异常
APIException
如果你的API依赖某个时不时会掉线的第三方服务你可能想要自己实现一个异常503 Service Unavailable的HTTP响应码你可以这么干
from rest_framework.exceptions import APIExceptionclass ServiceUnavailable(APIException):status_code 503default_detail Service temporarily unavailable, try again later.default_code service_unavailable检查 API 异常
有很多属性可以用来检查一个API异常的状态你可以用这些属性来构建专属你项目的自定义异常。
可用的属性和方法有
.detail - 以文字形式返回报错的细节描述。 .get_codes() - 返回报错的标识码。 .get_full_details() - 返回报错的细节描述以及报错的标识码。 大多数情况下报错的细节的返回结果很简单 print(exc.detail)
You do not have permission to perform this action.print(exc.get_codes())
permission_deniedprint(exc.get_full_details())
{message:You do not have permission to perform this action.,code:permission_denied}如果是验证类报错那报错细节就会是一个列表或者字典 print(exc.detail)
{name:This field is required.,age:A valid integer is required.}print(exc.get_codes())Zh
{name:required,age:invalid}print(exc.get_full_details())
{name:{message:This field is required.,code:required},age:{message:A valid integer is required.,code:invalid}}ParseError
签名: ParseError(detailNone, codeNone)
在访问request.data时如果请求中包含格式不正确的数据则该异常会被抛出。
默认情况下该异常会返回HTTP状态码为400 Bad Request的响应。