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.py
from django.contrib.auth import get_user_model # new
from rest_framework import serializers
from .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.py
from django.contrib.auth import get_user_model # new
from rest_framework import generics
from .models import Post
from .permissions import IsAuthorOrReadOnly
from .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.py
from 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.py
from django.contrib.auth import get_user_model
from rest_framework import viewsets # new
from .models import Post
from .permissions import IsAuthorOrReadOnly
from .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.py
from django.urls import path
from 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 复杂性的增加,如果您发现自己一遍又一遍地重复相同的端点模式,那么请查看视图集和路由器。
- 点赞
- 收藏
- 关注作者
评论(0)