欧博开户:第 10 篇 谈论接口

admin 4个月前 (06-19) 科技 38 0

作者:HelloGitHub-追梦人物

此前我们一直在操作博客文章(Post)资源,并借此先容了序列化器(Serializer)、视图集(Viewset)、路由器(Router)等 django-rest-framework 提供的便利工具,借助这些工具,就可以异常快速地完成 RESTful API 的开发。

谈论(Comment)是另一种资源,我们同样借助以上工具来完成对谈论资源的接口开发。

首先是设计谈论 API 的 URL,凭据 RESTful API 的设计规范,谈论资源的 URL 设计为:/comments/

对谈论资源的操作有获取某篇文章下的谈论列表和建立谈论两种操作,因此响应的 HTTP 请求和动作(action)对应如下:

HTTP请求 Action URL
GET list_comments /posts/:id/comments/
POST create /comments/

文章谈论列表 API 使用自界说的 action,放在 /post/ 接口的视图集下;揭晓谈论接口使用尺度的 create action,需要界说单独的视图集。

然后需要一个序列化器,用于谈论资源的序列化(获取谈论时),反序列化(建立谈论时)。有了编写文章序列化器的基础,谈论序列化器就是依葫芦画瓢的事。

comments/serializers.py

from rest_framework import serializers
from .models import Comment


class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = [
            "name",
            "email",
            "url",
            "text",
            "created_time",
            "post",
        ]
        read_only_fields = [
            "created_time",
        ]
        extra_kwargs = {"post": {"write_only": True}}

注重这里我们在 Meta 中增加了 read_only_fieldsextra_kwargs 的声明。

read_only_fields 用于指定只读字段的列表,由于 created_time 是自动天生的,用于纪录谈论公布时间,因此声明为只读的,不允许通过接口举行修改。

extra_kwargs 指定传入每个序列化字段的分外参数,这里给 post 序列化字段传入了 write_only 关键字参数,这样就将 post 声明为只写的字段,这样 post 字段的值仅在建立谈论时需要。而在返回的资源中,post 字段就不会泛起。

首先来实现建立谈论的接口,先为谈论建立一个视图集:

comments/views.py

from rest_framework import mixins, viewsets
from .models import Comment
from .serializers import CommentSerializer

class CommentViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    serializer_class = CommentSerializer

    def get_queryset(self):
        return Comment.objects.all()

视图集异常的简朴,混入 CreateModelMixin 后,视图集就实现了尺度的 create action。实在 create action 方式的实现也异常简朴,我们来学习一下 CreateModelMixin 的源码实现。

class CreateModelMixin:
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': str(data[api_settings.URL_FIELD_NAME])}
        except (TypeError, KeyError):
            return {}

焦点逻辑在 create 方式:首先取到绑定了用户提交数据的序列化器,用于反序列化。接着挪用 is_valid 方式校验数据合法性,若是不合法,会直接抛出异常(raise_exception=True)。否则就执行序列化的 save 逻辑将谈论数据存入数据库,最后返回响应。

接着在 router 里注册 CommentViewSet 视图集:

router.register(r"comments", comments.views.CommentViewSet, basename="comment")

进入 API 交互后台,可以看到首页列出了 comments 接口的 URL,点击进入 /comments/ 后可以看到一个谈论表单,在这里可以提交谈论数据与建立谈论的接口举行交互。

接下来实现获取谈论列表的接口。通常情况下,我们都是只获取某篇博客文章下的谈论列表,因此我们的 API 设计成了 /posts/:id/comments/。这个接口具有很强的语义,异常相符 RESTful API 的设计规范。

由于接口位于 /posts/ 空间下,因此我们在 PostViewSet 添加自界说 action 来实现,先来看代码:

blog/views.py

class PostViewSet(
    mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet
):
    # ...
    
    @action(
            methods=["GET"],
            detail=True,
            url_path="comments",
            url_name="comment",
            pagination_class=LimitOffsetPagination,
            serializer_class=CommentSerializer,
    )
    def list_comments(self, request, *args, **kwargs):
        # 凭据 URL 传入的参数值(文章 id)获取到博客文章纪录
        post = self.get_object()
        # 获取文章下关联的所有谈论
        queryset = post.comment_set.all().order_by("-created_time")
        # 对谈论列表举行分页,凭据 URL 传入的参数获取指定页的谈论
        page = self.paginate_queryset(queryset)
        # 序列化谈论
        serializer = self.get_serializer(page, many=True)
        # 返回分页后的谈论列表
        return self.get_paginated_response(serializer.data)

action 装饰器我们在上一篇教程中举行了详细说明,这里我们再一次接触到 action 装饰器更为深入的用法,可以看到我们除了设置 methodsdetailurl_path 这些参数外,还通过设置 pagination_classserializer_class 来笼罩原本在 PostViewSet 中设置的这些类属性的值(例如对于分页,PostViewSet 默以为我们之前设置的 PageNumberPagination,而这里我们替换为 LimitOffsetPagination)。

list_comments 方式逻辑异常清晰,注释中给出了详细的说明。另外还可以看到我们挪用了一些辅助方式,例如 paginate_queryset 对查询集举行分页;get_paginated_response 返回分页后的 HTTP 响应,这些方式实在都是 GenericViewSet 提供的通用辅助方式,源码也并不庞大,若是不用这些方式,我们自己也可以轻松实现,但既然 django-rest-framework 已经为我们写好了,直接复用就行,详细的实现请人人通过阅读源码举行学习。

现在进入 API 交互后台,进入某篇文章的详细接口,例如接见 /api/posts/5/,Extra Actions 下拉框中可以看到 List comments 的选项:

点击 List comments 即可进入这篇文章下的谈论列表接口,获取这篇文章的谈论列表资源了:

关注民众号加入交流群

,

欧博客户端

欢迎进入欧博客户端(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。

dafa888体育声明:该文看法仅代表作者自己,与本平台无关。转载请注明:欧博开户:第 10 篇 谈论接口

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:738
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1179
  • 评论总数:436
  • 浏览总数:22043