在DRF source code中,有一个get_serializer方法。它不是从对象继承而来的,它不是CreateModelMixin类中的方法。这种方法来自哪里?
serializer = self.get_serializer(data=request.data)
这里是上下文的大块代码。
from __future__ import unicode_literals
from rest_framework import status
from rest_framework.response import Response
from rest_framework.settings import api_settings
class CreateModelMixin(object):
"""
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': data[api_settings.URL_FIELD_NAME]}
except (TypeError, KeyError):
return {}
答案 0 :(得分:12)
CreateModelMixin
以及所有其他mixin类(例如ListModelMixin
,UpdateModelMixin
等)在rest_framework/mixins.py
文件中定义。
这些mixin类提供模型上的所有基本CRUD
操作。您只需在通用视图中定义serializer_class
和queryset
即可执行所有这些操作。 DRF已在单独的mixin类中分离出这些常用功能,以便它们可以在视图中注入/混合并在需要时使用。
在DRF源代码中,有
get_serializer
方法。事实并非如此 继承自object并且它不是CreateModelMixin
中的方法 类。这种方法来自哪里?
在GenericAPIView
中,定义了get_serializer
方法。不同mixin类和GenericAPIView
类的组合为我们different generic views提供了不同的用例。
class GenericAPIView(views.APIView):
"""
Base class for all other generic views.
"""
def get_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
其他通用视图会继承相关mixin
和GenericAPIView
。
例如。 CreateAPIView
继承CreateModelMixin
和GenericAPIView
以提供 create-only
端点。
# rest_framework/generics.py
class CreateAPIView(mixins.CreateModelMixin,
GenericAPIView):
...
答案 1 :(得分:1)
您可以查看方法的__file__
或__module__
成员(如果有)以了解相关信息。 inspect
也有getsourcefile
和getsourcelines
使用来自函数代码对象的数据,具体来说,<function>.f_code.co_filename
和.co_firstline
。
例如,这将检索从DictMixin
继承的方法的源信息:
>>> c=ConfigParser._Chainmap()
>>> f=c.__len__
>>> dump(f.__code__) #my custom function that dumps attributes
<...>
co_filename : /usr/lib/python2.7/UserDict.py
co_firstlineno : 179
<...>
#same with inspect
>>> inspect.getsourcefile(f)
'/usr/lib/python2.7/UserDict.py'
>>> inspect.getsourcelines(f)
([' def __len__(self):\n', ' return len(self.keys())\n'], 179)
>>> inspect.getsource(f)
' def __len__(self):\n return len(self.keys())\n'
#same with __file__
>>> sys.modules[f.__module__].__file__
'/usr/lib/python2.7/UserDict.pyc'
答案 2 :(得分:1)
如果您了解类继承(尽管并不建议您不这样做),那么它会有所帮助。
CreateModelMixin
将由基于类的视图使用,例如:
class YourViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
get_serializer
是GenericViewSet
可用的方法(尽管可能还有其他View类可用)。
因此,基本上,如果您将使用CreateModelMixin
,则仅get_serializer
不可用。 (您可能还是不会这样做)。仅仅是因为您从CreateModelMixin
之外的另一个类继承而来,get_serializer
方法在执行create
方法时才可用。
我可以举一个简单的例子说明正在发生的事情。只是为了更简单地概述正在发生的事情。
免责声明:您可能要记住,我是一名初级开发人员,所以这可能不是那里最有Python风格的代码:
class MyMixin:
def create(self):
serializer = self.get_serializer()
return serializer
class FakeView:
def get_serializer(self):
return "Sadly I am just a string, but I could've been a serializer."
class MyFakeView(MyMixin, FakeView):
pass
view = MyFakeView()
serializer = view.create()
print(serializer)
执行此操作将显示:
Sadly I am just a string, but I could've been a serializer.
如果您要像下面那样定义MyFakeView
,
class MyFakeView(MyMixin):
pass
您将收到以下错误:
AttributeError: 'MyFakeView' object has no attribute 'get_serializer'