mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-12-01 22:14:06 +03:00
37f210a455
Co-authored-by: Lucidiot <lucidiot@protonmail.com> Co-authored-by: dongfangtianyu <dongfangtianyu@qq.com>
80 lines
2.3 KiB
Python
80 lines
2.3 KiB
Python
"""
|
|
inspectors.py # Per-endpoint view introspection
|
|
|
|
See schemas.__init__.py for package overview.
|
|
"""
|
|
from weakref import WeakKeyDictionary
|
|
|
|
from rest_framework.settings import api_settings
|
|
|
|
|
|
class ViewInspector:
|
|
"""
|
|
Descriptor class on APIView.
|
|
|
|
Provide subclass for per-view schema generation
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.instance_schemas = WeakKeyDictionary()
|
|
|
|
def __get__(self, instance, owner):
|
|
"""
|
|
Enables `ViewInspector` as a Python _Descriptor_.
|
|
|
|
This is how `view.schema` knows about `view`.
|
|
|
|
`__get__` is called when the descriptor is accessed on the owner.
|
|
(That will be when view.schema is called in our case.)
|
|
|
|
`owner` is always the owner class. (An APIView, or subclass for us.)
|
|
`instance` is the view instance or `None` if accessed from the class,
|
|
rather than an instance.
|
|
|
|
See: https://docs.python.org/3/howto/descriptor.html for info on
|
|
descriptor usage.
|
|
"""
|
|
if instance in self.instance_schemas:
|
|
return self.instance_schemas[instance]
|
|
|
|
self.view = instance
|
|
return self
|
|
|
|
def __set__(self, instance, other):
|
|
self.instance_schemas[instance] = other
|
|
if other is not None:
|
|
other.view = instance
|
|
|
|
@property
|
|
def view(self):
|
|
"""View property."""
|
|
assert self._view is not None, (
|
|
"Schema generation REQUIRES a view instance. (Hint: you accessed "
|
|
"`schema` from the view class rather than an instance.)"
|
|
)
|
|
return self._view
|
|
|
|
@view.setter
|
|
def view(self, value):
|
|
self._view = value
|
|
|
|
@view.deleter
|
|
def view(self):
|
|
self._view = None
|
|
|
|
|
|
class DefaultSchema(ViewInspector):
|
|
"""Allows overriding AutoSchema using DEFAULT_SCHEMA_CLASS setting"""
|
|
def __get__(self, instance, owner):
|
|
result = super().__get__(instance, owner)
|
|
if not isinstance(result, DefaultSchema):
|
|
return result
|
|
|
|
inspector_class = api_settings.DEFAULT_SCHEMA_CLASS
|
|
assert issubclass(inspector_class, ViewInspector), (
|
|
"DEFAULT_SCHEMA_CLASS must be set to a ViewInspector (usually an AutoSchema) subclass"
|
|
)
|
|
inspector = inspector_class()
|
|
inspector.view = instance
|
|
return inspector
|