【7.0】作业

发布时间 2023-07-31 12:29:36作者: Chimengmeng

【一】在原生Django中向响应头添加数据

  • 在您的视图函数中

    • 使用HttpResponse类创建响应对象。
  • 通过调用响应对象的['key']来设置相应的头字段和值。

  • 示例

from django.http import HttpResponse

def your_view(request):
    # 创建 HttpResponse 对象
    response = HttpResponse('Hello, World!')

    # 添加自定义的响应头字段和值
    response['Custom-Header'] = 'Custom Value'

    return response
  • 在上述示例中
    • Custom-Header是自定义的响应头字段
    • Custom Value是相应的值。

【二】编写一个post接口

  • 只能接受json编码格式,响应json格式,响应头中加入Access-Control-Allow-Origin = "*"
from django.http import JsonResponse

def your_post_view(request):
    # 检查请求方法是否为 POST
    if request.method == 'POST':
        # 检查请求头中的 Content-Type 是否为 application/json
        if request.content_type == 'application/json':
            try:
                # 尝试解析请求体中的 JSON 数据
                data = json.loads(request.body)
                
                # 在这里进行相应的业务处理,生成响应数据
                
                # 创建 JsonResponse 对象,传入响应数据
                response_data = {
                    'message': 'Success',
                    'data': 'Your response data'
                }
                response = JsonResponse(response_data)

                # 设置响应头字段 Access-Control-Allow-Origin 为 '*'
                response['Access-Control-Allow-Origin'] = '*'
                
                return response
            except ValueError:
                # 如果无法解析请求体中的 JSON 数据,返回错误响应
                error_response = JsonResponse({'error': 'Invalid JSON data'})
                error_response.status_code = 400
                return error_response
        else:
            # 如果 Content-Type 不是 application/json,返回错误响应
            error_response = JsonResponse({'error': 'Invalid Content-Type. Only application/json is supported.'})
            error_response.status_code = 415
            return error_response
    else:
        # 如果请求方法不是 POST,返回错误响应
        error_response = JsonResponse({'error': 'Invalid request method'})
        error_response.status_code = 405
        return error_response
  • 在创建 JsonResponse 对象时,将响应数据作为参数传入。
  • 然后,使用 response['Access-Control-Allow-Origin'] = '*'Access-Control-Allow-Origin 设置为 *,以实现允许来自任何域的跨域请求。

【三】基于GenericAPIView编写图书5个接口

  • 带出版社和作者
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer

class BookListCreateView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
  • 首先导入了 generics 模块、Book 模型和 BookSerializer 序列化器。
    • 然后,我们定义了两个基于 GenericAPIView 的视图类:
      • BookListCreateView
        • BookListCreateView 是一个用于获取图书列表和创建新图书的视图类。
        • 我们设置了 queryset 属性,将其指向所有的图书对象,并将 serializer_class 属性设置为 BookSerializer,该序列化器定义了如何序列化和反序列化图书对象。这个视图类已经带有默认的 GET 和 POST 方法的实现。
      • BookRetrieveUpdateDestroyView
      • BookRetrieveUpdateDestroyView 是一个用于获取、更新和删除特定图书的视图类。
      • 与上面的视图类相似,我们设置了 querysetserializer_class 属性。
      • 这个视图类已经带有默认的 GET、PUT、PATCH 和 DELETE 方法的实现。

【四】封装5个类

ListModelMixin
CreateModelMixin
UpdateModelMixin
DestroyModelMixin
RetrieveModelMixin
  • 实现这种效果
class PublishView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier
    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class PublishDetailView(GenericAPIView,DestroyModelMixin,UpdateModelMixin,RetrieveModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerialzier

    def get(self, request, pk):
        return self.retrieve(request, pk)
    
    def put(self, request, pk):
        return self.update(request, pk)
    def delete(self, request, pk):
        return self.destroy(request, pk)
  • 示例实现对 Publish 模型的列表视图和详情视图进行封装:
from rest_framework import generics
from rest_framework.mixins import ListModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin
from .models import Publish
from .serializers import PublishSerializer

class PublishListView(generics.GenericAPIView, ListModelMixin, CreateModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class PublishDetailView(generics.GenericAPIView, DestroyModelMixin, UpdateModelMixin, RetrieveModelMixin):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)
  • 在上述代码中,我们导入了 generics 模块以及针对不同操作的混合类
    • ListModelMixinCreateModelMixinUpdateModelMixinDestroyModelMixinRetrieveModelMixin
    • 我们还导入了 Publish 模型和 PublishSerializer 序列化器。
  • 然后
    • 我们定义了 PublishListViewPublishDetailView 两个视图类,分别继承了 GenericAPIView 和对应的混合类。
  • PublishListView 类中
    • 我们设置了 queryset 属性
      • 将其指向所有的 Publish 对象,并设置了 serializer_class 属性为 PublishSerializer
    • 然后,我们重写了 get()post() 方法
      • 分别调用 list()create() 方法来实现对应的列表和创建操作。
  • PublishDetailView 类中,我们同样设置了 querysetserializer_class 属性。
    • 然后,我们重写了 get()put()delete() 方法,分别调用 retrieve()update()destroy() 方法来实现对应的详情、更新和删除操作。

【五】基于DRF的Response,封装一个自己的Response,使它更符合我们规范

  • 基于 DRF 的 Response 进行封装的示例:
from rest_framework.response import Response

class CustomResponse(Response):
    def __init__(self, code=100, msg="成功", data=None, status=None, template_name=None, headers=None, content_type=None):
        response_data = {
            'code': code,
            'msg': msg,
            'data': data
        }
        super().__init__(response_data, status, headers, content_type)
  • 在上述代码中

    • 我们自定义了一个名为 CustomResponse 的响应类,继承自 DRF 的 Response 类。
  • __init__ 方法中,我们定义了几个参数

    • 包括 codemsgdata
    • 这些参数分别用于指定响应的状态码、消息和数据。
  • 然后我们创建了一个 response_data 字典,将传入的参数赋值给对应的键,并将其作为第一个参数传递给父类的 __init__ 方法。

  • 通过这样的封装,可以使用自定义的 CustomResponse 类来创建响应对象,例如:

def my_view(request):
    data = {'name': 'John', 'age': 25}
    return CustomResponse(code=100, msg='成功', data=data)
  • 这样返回的响应将符合您的规范,具有如下格式:
{
  "code": 100,
  "msg": "成功",
  "data": {
    "name": "John",
    "age": 25
  }
}

【六】封装一个视图类,实现某个表的5个接口

  • 使用方式如下
# 视图类只需要这么写,就有5个接口
class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

【1】获取所有发布信息的接口(ListAPIView):

from rest_framework.generics import ListAPIView
from your_app.models import Publish
from your_app.serializers import PublishSerializer

class PublishListView(ListAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

【2】获取单个发布信息的接口(RetrieveAPIView):

from rest_framework.generics import RetrieveAPIView
from your_app.models import Publish
from your_app.serializers import PublishSerializer

class PublishDetailView(RetrieveAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

【3】创建发布信息的接口(CreateAPIView):

from rest_framework.generics import CreateAPIView
from your_app.models import Publish
from your_app.serializers import PublishSerializer

class PublishCreateView(CreateAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

【4】更新发布信息的接口(UpdateAPIView):

from rest_framework.generics import UpdateAPIView
from your_app.models import Publish
from your_app.serializers import PublishSerializer

class PublishUpdateView(UpdateAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

【5】删除发布信息的接口(DestroyAPIView):

from rest_framework.generics import DestroyAPIView
from your_app.models import Publish
from your_app.serializers import PublishSerializer

class PublishDeleteView(DestroyAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

【七】研究importlib,如何动态导入模块

【八】自己封装出9个视图子类

  • 能方便实现5个接口中某一个或多个

    class PublishView(ListAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerialzier
    
    class PublishDetailView(DestroyAPIView):
        queryset = Publish.objects.all()
        serializer_class = PublishSerialzier