写点什么

Django API 开发:视图设置和路由

作者:宇宙之一粟
  • 2022 年 6 月 09 日
  • 本文字数:3436 字

    阅读完需:约 11 分钟

Django API 开发:视图设置和路由

前言

视图集路由器是 Django REST Framework 中的工具,可以加速 API 开发。 它们是视图和 URL 之上的附加抽象层。 主要好处是单个视图集可以替换多个相关视图。 路由器可以自动为开发人员生成 URL。 在具有许多端点的大型项目中,这意味着开发人员必须编写更少的代码。 可以说,与一长串的单个视图和 URL 相比,对于经验丰富的开发人员而言,与少量视图集和路由器组合相比,它更易于理解和推理。


在本章中,我们将向现有项目中添加两个新的 API 端点,并了解如何从视图和 URL 切换到视图集和路由器可以用更少的代码实现相同的功能。

用户终端

当前,我们的项目中具有以下 API 端点。 它们都以 api/v1/ 开头,为简洁起见,未显示它们:



前两个端点是我们创建的,而 django-rest-auth 提供了另外五个端点。 现在让我们添加两个其他端点,以列出所有用户和单个用户。 这是许多 API 中的常见功能,它将使我们更清楚地理解为什么将我们的视图和 URL 重构为视图集和路由器是有意义的。


传统 Django 具有内置的 User 模型类,我们已经在上一篇文章中使用了该类进行身份验证。 因此,我们不需要创建新的数据库模型。 相反,我们只需要连接新的端点即可。 此过程始终涉及以下三个步骤:


  • 新增模型序列化器

  • 新增每个端点视图

  • 新增每个端点的 URL 路由


从我们的序列化器开始。 我们需要导入 User 模型,然后创建一个使用它的 UserSerializer 类。 然后将其添加到我们现有的 posts/serializers.py文件中。


# posts/serializers.pyfrom django.contrib.auth import get_user_model # new from rest_framework import serializersfrom .models import Post

class PostSerializer(serializers.ModelSerializer): class Meta: model = Post fields = ('id', 'author', 'title', 'body', 'created_at',)
class UserSerializer(serializers.ModelSerializer): # new class Meta: model = get_user_model() fields = ('id', 'username',)
复制代码


值得注意的是,虽然我们在这里使用 get_user_model 来引用 User 模型,但实际上在 Django 中有3种不同的方式来引用 User 模型。


通过使用 get_user_model ,我们确保我们引用的是正确的用户模型,无论是默认用户模型还是新 Django 项目中经常定义的自定义用户模型


接下来,我们需要为每个端点定义视图。 首先将 UserSerializer 添加到导入列表中。 然后创建列出所有用户的 UserList 类和提供单个用户详细视图的 UserDetail 类。 就像我们的帖子视图一样,我们可以在此处使用 ListCreateAPIView 和 RetrieveUpdateDestroyAPIView。


对于每个端点,我们只需要只读或 GET 功能。 这意味着我们可以使用 ListAPIView 和 RetrieveUpdateDestroyAPIView 。 我们还需要通过 get_user_model 引用用户模型,以便将其导入第一行。


# posts/views.pyfrom django.contrib.auth import get_user_model # new from rest_framework import generics
from .models import Postfrom .permissions import IsAuthorOrReadOnlyfrom .serializers import PostSerializer, UserSerializer # new

class PostList(generics.ListCreateAPIView): 0 queryset = Post.objects.all() serializer_class = PostSerializer class PostDetail(generics.RetrieveUpdateDestroyAPIView): permission_classes = (IsAuthorOrReadOnly,) queryset = Post.objects.all() serializer_class = PostSerializer class UserList(generics.ListCreateAPIView): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer class UserDetail(generics.RetrieveUpdateDestroyAPIView): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer
复制代码


如果您注意到,这里有很多重复。 Post 视图和 User 视图都具有完全相同的 queryset 和 serializer_class。

最后,我们有了 URL 路由。 确保导入新的 UserList 和 UserDetail 视图。 然后,我们可以为每个用户使用前缀 users/


# posts/urls.pyfrom django.urls import path
from .views import UserList, UserDetail, PostList, PostDetail # new
urlpatterns = [ path('users/', UserList.as_view()), # new path('users/<int:pk>/', UserDetail.as_view()), # new path('', PostList.as_view()), path('<int:pk>/', PostDetail.as_view()),]
复制代码


我们完成了。 确保本地服务器仍在运行,并跳至可浏览的 API 以确认一切正常。


我们的用户列表端点位于 http://127.0.0.1:8000/api/v1/users/



状态代码为 200 OK ,表示一切正常。 我们可以看到三个现有用户。


每个用户的主键上都有一个用户详细信息终结点。 因此,我们的超级用户帐户位于:http://127.0.0.1:8000/api/v1/users/1/



视图集

视图集是一种将多个相关视图的逻辑组合到单个类中的方法。 换句话说,一个视图集可以替换多个视图。 当前,我们有四个视图:两个用于博客帖子,两个用于用户。 相反,我们可以使用两个视图集来模仿相同的功能:一个用于博客文章,另一个用于用户。


折衷方案是,对于不十分熟悉视图集的其他开发人员,可读性会有所下降。 所以这是一个权衡。当我们交换视图集时,代码在更新后的 posts/views.py 文件中是这样的。


# posts/views.pyfrom django.contrib.auth import get_user_model from rest_framework import viewsets # new
from .models import Postfrom .permissions import IsAuthorOrReadOnlyfrom .serializers import PostSerializer, UserSerializer

class PostViewSet(viewsets.ModelViewSet): # new permission_classes = (IsAuthorOrReadOnly,) queryset = Post.objects.all() serializer_class = PostSerializer class UserViewSet(viewsets.ModelViewSet): # new queryset = get_user_model().objects.all() serializer_class = UserSerializer
复制代码


在顶部,而不是从 rest_framework 导入泛型,我们现在在第二行导入视图集。 然后,我们使用 ModelViewSet,它为我们提供了列表视图和详细信息视图。 而且,我们不再需要像以前一样为每个视图重复相同的 queryset 和 serializer_class 。

Routers 路由

直接与视图集一起使用,以自动为我们生成 URL 模式。 我们当前的 posts/urls.py 文件具有四个 URL 模式:两个用于博客文章,两个用于用户。相反,我们可以为每个视图集采用一条路由。 因此,使用两个路由而不是四个 URL 模式。 听起来更好吧?


Django REST Framework 具有两个默认路由器:SimpleRouter 和 DefaultRouter 。 我们将使用 SimpleRouter,但也可以为更多高级功能创建自定义路由器。


更新后的代码如下所示:


# posts/urls.pyfrom django.urls import pathfrom rest_framework.routers import SimpleRouter
from .views import UserViewSet, PostViewSet
router = SimpleRouter()router.register('users', UserViewSet, base_name='users') router.register('', PostViewSet, base_name='posts')
urlpatterns = router.urls
复制代码


在最上面一行,将导入 SimpleRouter 及其视图。 路由器设置为 SimpleRouter,我们为用户和帖子“注册”每个视图集。 最后,我们将 URL 设置为使用新路由器。


继续并立即检查我们的四个端点! 用户列表是相同的。


但是,局部视图有些不同。 现在它被称为“用户实例”,而不是“用户详细信息”,并且还有一个附加的“删除”选项内置于ModelViewSet中。



可以自定义视图集,但是一个重要的折衷是用视图集编写更少的代码,这是默认设置,它可能需要一些其他配置才能完全匹配您想要的内容。


转到发布列表,我们可以看到它是相同的:



重要的是,我们的权限仍然有效。 使用我们的 testuser2 帐户登录时,Post Instance 为只读。



但是,如果我们使用超级用户帐户(该日志是单独的博客文章的作者)登录的,那么我们将具有完整的读写-编辑-删除权限。



总结

视图集和路由器是一种强大的抽象,可减少开发人员必须编写的代码量。 但是,这种简洁性是以牺牲初始学习曲线为代价的。 最初几次使用视图集和路由器而不是视图和 URL 模式会感到很奇怪。


最终,何时向项目添加视图集和路由器的决定是相当主观的。 一个好的经验法则是从视图和 URL 开始。 随着 API 复杂性的增加,如果您发现自己一遍又一遍地重复相同的端点模式,那么请查看视图集和路由器。

发布于: 刚刚阅读数: 4
用户头像

宇宙古今无有穷期,一生不过须臾,当思奋争 2020.05.07 加入

🏆InfoQ写作平台-第二季签约作者 🏆 混迹于江湖,江湖却没有我的影子 热爱技术,专注于后端全栈,轻易不换岗 拒绝内卷,工作于软件工程师,弹性不加班 热衷分享,执着于阅读写作,佛系不水文

评论

发布
暂无评论
Django API 开发:视图设置和路由_django_宇宙之一粟_InfoQ写作社区