Python 学习笔记(十九)--Django REST Framework之GenericAPIView(二)
13 GenericAPIView中的get_object方法
get_object方法,目的是为了获取一条数据。
def get_object(self): """ Returns the object the view is displaying. You may want to override this if you need to provide non-standard queryset lookups. Eg if objects are referenced using multiple keyword arguments in the url conf. """ queryset = self.filter_queryset(self.get_queryset()) ###返回所有数据 # Perform the lookup filtering. lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field ###定义变量,lookup_url_kwarg就是pk,路由中有名分组分出来的pk values 值。 assert lookup_url_kwarg in self.kwargs, ( 'Expected view %s to be called with a URL keyword argument ' 'named "%s". Fix your URL conf, or set the `.lookup_field` ' 'attribute on the view correctly.' % (self.__class__.__name__, lookup_url_kwarg) ) filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} ###构造出一个字典对象,{pk:有名分组分出来的values值}。
###self.kwargs[lokup_url_kwarg]对应的就是浏览器地址中要查询的pk值。 obj = get_object_or_404(queryset, **filter_kwargs) # May raise a permission denied self.check_object_permissions(self.request, obj) return obj
lookup_field 与 lookup_url_kwarg的说明。
# If you want to use object lookups other than pk, set 'lookup_field'.
# For more complex lookup requirements override `get_object()`.
lookup_field = 'pk'
lookup_url_kwarg = None
14其中调用到的方法get_object_or_404
def get_object_or_404(queryset, *filter_args, **filter_kwargs): """ Same as Django's standard shortcut, but make sure to also raise 404 if the filter_kwargs don't match the required types. """ try: return _get_object_or_404(queryset, *filter_args, **filter_kwargs) except (TypeError, ValueError, ValidationError): raise Http404
进一步调用_get_object_or_404
from django.shortcuts import get_object_or_404 as _get_object_or_404
源码如下:
def get_object_or_404(klass, *args, **kwargs): """ Use get() to return an object, or raise a Http404 exception if the object does not exist. klass may be a Model, Manager, or QuerySet object. All other passed arguments and keyword arguments are used in the get() query. Like with QuerySet.get(), MultipleObjectsReturned is raised if more than one object is found. """ queryset = _get_queryset(klass) if not hasattr(queryset, 'get'): klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__ raise ValueError( "First argument to get_object_or_404() must be a Model, Manager, " "or QuerySet, not '%s'." % klass__name ) try: return queryset.get(*args, **kwargs) except queryset.model.DoesNotExist: raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
最核心的代码 queryset.get(*args, **kwargs)
15 自动生成路由
第一步,urls文件中导入routers
from rest_framework import routers
第二步,导入两个类:routers.DefaultRouter 和 routers.SimpleRouter
实例化等到对象
例如:
router = routers.SimpleRouter()
第三步,注册
router.register()
register 方法的源码,如下
def register(self, prefix, viewset, basename=None): ###至少传入两个参数 prefix--前缀 和 viewset---继承自ModelViesSet的视图类;注意所谓的前缀说的是url前缀,
###需要注意的是,这个前缀后面不要加'\'字符了.
###basename,就是常说的别名,反向解析使用。 if basename is None: basename = self.get_default_basename(viewset) self.registry.append((prefix, viewset, basename)) # invalidate the urls cache if hasattr(self, '_urls'): del self._urls
第四步,添加到路由中
router.urls ##这个对象就是自动生成的路由
所以,添加代码就是 urlpatterns += router.urls
16. ViewSet
from rest_framework.viewsets import ViewSet
ViewSet的源码
class ViewSet(ViewSetMixin, views.APIView): """ The base ViewSet class does not provide any actions by default. """ pass
继承APIView和ViewSetMixin;在ViewSet中,没有提供任何动作action方法,需要使用者自己实现action方法。
ViewSet视图集类不再限制视图方法名只允许get()、post()等这种情况了,而是实现允许开发者根据自己的需要定义自定义方法名,例如 list() 、create() 等,然后经过路由中使用http和这些视图方法名进行绑定调用。ViewSet 中实现了以下几个方法。
list #get 请求 返回全部查询 create #post 请求 处理表单提交数据 retrieve #get 请求 通过pk 查询单个信息 update #patch 请求 通过pk 修改数据 destroy #delete 请求 通过pk 删除数据
通过路由指向,绑定视图类中对应的方法。
格式为
path(路由,绑定的试图类.as_view({请求方式:绑定的视图类中具体的方法}))
使用as_view()方法,定义好action与请求方法的对应关系,可以将action动作与具体的请求方法对应上。
例如
urlpatterns = format_suffix_patterns([ path('', IndexViewSet.as_view({'get': 'list'})), path('<int:pk>/', XXXX.as_view({'get': 'retrieve'})), path('post/',XXXXX.as_view({'post': 'create'})), path('patch/<int:pk>/',XXXXX.as_view({'patch':'update'})), path('destroy/<int:pk>/', XXXXX.as_view({'delete':'destroy'})) ])
17. 几种ViewSet的继承关系
说明
(1)GenericViewSet
GenericViewSet 继承自GenericAPIView 和 ViewSetMixin,作用让视图集的代码变得更加通用,抽离独特代码作为视图类的属性。
使用ViewSet通常并不方便,因为list、retrieve、create、update、destroy等方法都需要自己编写,而这些方法与Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写。但是Mixin扩展类依赖于GenericAPIView,所以还需要继承GenericAPIView。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库