Mysql双主架构及其异常
334 2023-04-03 04:18:03
django-rest-framework学习之路-8-Request请求与Response返回
snippets/views.py内容变成了
from django.contrib.auth.models import Userfrom rest_framework import renderers, viewsets, permissionsfrom rest_framework.decorators import actionfrom rest_framework.request import Requestfrom rest_framework.response import Responsefrom snippets.models import Snippetfrom snippets.permissions import IsOwnerOrReadOnlyfrom snippets.serializers import SnippetSerializer, UserSerializerclass UserViewSet(viewsets.ModelViewSet): """ 此视图自动提供`list`和`detail`操作。 """ queryset = User.objects.all() serializer_class = UserSerializerclass SnippetViewSet(viewsets.ModelViewSet): """ 此视图自动提供`list`,`create`,`retrieve`,`update`和`destroy`操作。 另外我们还提供了一个额外的`highlight`操作。 """ queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,) @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer]) def highlight(self, request, *args, **kwargs): snippet = self.get_object() return Response(snippet.highlighted) def perform_create(self, serializer): serializer.save() def create(self, request: Request, *args, **kwargs): print("POST方法进入create函数") print(f"request dict:{request.__dict__}") print(f"data:{request.data}") print(f"query_params:{request.query_params}") print(f"parsers:{request.parsers}") print(f"user:{request.user}") print(f"auth:{request.auth}") print(f"method:{request.method}") print(f"content_type:{request.content_type}") print(f"stream:{request.stream}") return super().create(request, *args, **kwargs)
snippets/serializers.py内容变成了
from django.contrib.auth.models import Userfrom rest_framework import serializersfrom snippets.models import Snippetclass SnippetSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.username') highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html') class Meta: model = Snippet fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style')class UserSerializer(serializers.ModelSerializer): snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True) class Meta: model = User fields = ('url', 'id', 'username', 'snippets')
request.data 返回请求正文的解析内容
例如请求:
curl --location --request POST 'http://127.0.0.1:8000/snippets/snippets/' \
--header 'Host: 127.0.0.1' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "标题~~~",
"code": "代码~~~",
"linenos": false,
"language": "c",
"style": "friendly",
"A":1,
"B":"2"
}'
这样可以获取完整的body数据
print(f"query_params:{request.query_params}")
例如
curl --location --request POST --X POST 'http://127.0.0.1:8000/snippets/snippets/?query1=1&query2=哈哈&query2=嘿嘿'
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/'
--header 'Host: 127.0.0.1'
--header 'Content-Type: application/json'
--data '{
"title": "标题~",~",
"code": "代码
"linenos": false,
"language": "c",
"style": "friendly",
"A": 1,
"B": "2"
}'
request.method 返回请求的HTTP方法的 大写 字符串表示形式。
透明地支持基于浏览器的 PUT, PATCH 和 DELETE 表单。
request.user 通常返回一个 django.contrib.auth.models.User 实例, 尽管该行为取决于所使用的的认证策略。
如果请求未认证则 request.user 的默认值为 django.contrib.auth.models.AnonymousUser的一个实例。
request.auth 返回任何其他身份验证上下文。 request.auth 的确切行为取决于所使用的的认证策略,但它通常可以是请求被认证的token的实例。
如果请求未认证或者没有其他上下文,则 request.auth 的默认值为 None.
APIView类或@api_view装饰器将根据view中设置的parser_classes集合或基于DEFAULT_PARSER_CLASSES设置,确保此属性自动设置为Parser实例列表。
你通常并不需要访问这个属性。
Note: 如果客户端发送格式错误的内容,则访问request.data可能会引发ParseError。默认情况下REST framework的 APIView类或@api_view装饰器将捕获错误并返回400 Bad Request响应。
如果客户端发送具有无法解析的内容类型的请求,则会引发 UnsupportedMediaType 异常, 默认情况下会捕获该异常并返回 415 Unsupported Media Type 响应。
APIView 类或 @api_view 装饰器将根据在view中设置的 authentication_classes 或基于DEFAULT_AUTHENTICATORS 设置,确保此属性自动设置为 Authentication 实例的列表。
你通常并不需要访问此属性。
request.content_type 返回表示HTTP请求正文的媒体类型的字符串对象,如果未提供媒体类型,则返回空字符串。
你通常不需要直接访问请求的内容类型,因为你通常将依赖于REST framework的默认请求解析行为。
如果你确实需要访问请求的内容类型,你应该使用 .content_type 属性,而不是使用 request.META.get('HTTP_CONTENT_TYPE'), 因为它为基于浏览器的非表单内容提供了透明的支持。
request.stream 返回一个表示请求主体内容的流。
你通常不需要直接访问请求的内容类型,因为你通常将依赖于REST framework的默认请求解析行为。
PS:(通常来说使用APIView类和@api_view函数即可,无需自己处理返回,除非自定义)
EST framework 通过提供一个 Response 类来支持 HTTP content negotiation,该类允许你返回可以呈现为多种内容类型的内容,具体取决于客户端的请求。
Response 类是 Django中 SimpleTemplateResponse 类的一个子类。Response 对象用Python基本数据类型初始化。 然后REST framework 使用标准的HTTP content negotiation 来确定如何呈现最终的响应内容。
你并不需要一定是用 Response 类,你可以从你的视图返回常规的 HttpResponse 或者 StreamingHttpResponse 对象。使用Response类只提供了一个可以呈现多种格式的更好的界面来返回 content-negotiated 的 Web API 响应。
除非由于某种原因你要对 REST framework 做大量的自定义,否则你应该始终对返回对象的views使用 APIView 类或者 @api_view 函数。这样做可以确保视图在返回之前能够执行 content negotiation 并且为响应选择适当的渲染器。
Request 对象的未渲染内容。
HTTP 响应的数字状态吗。
response的呈现内容。 .render() 方法必须先调用才能访问 .content 。
template_name 只有在使用 HTMLRenderer 或者其他自定义模板作为response的渲染器时才需要提供该属性。
将用于呈现response的render实例。
自动通过 APIView 或者 @api_view 在view返回response之前设置。
由 content negotiation 阶段选择的媒体类型。
自动通过 APIView 或者 @api_view 在view返回response之前设置。
一个将传递给渲染器的.render()方法的附加上下文信息字典。
自动通过 APIView 或者 @api_view 在view返回response之前设置。
Response 类扩展了 SimpleTemplateResponse,并且所有常用的属性和方法都是提供的。比如你可以使用标准的方法设置response的header信息:
response = Response()response['Cache-Control'] = 'no-cache'
Signature: .render()
和其他的 TemplateResponse 一样,调用该方法将response的序列化数据呈现为最终的response内容。 当 .render() 被调用时, response的内容将被设置成在 accepted_renderer实例上调用 .render(data, accepted_media_type, renderer_context) 方法返回的结果。
你通常并不需要自己调用 .render() ,因为它是由Django的标准响应周期来处理的。