在 Django Rest Framework 中生成 OpenAPI Schema:更新视图集中的 URL 关键字
Posted
技术标签:
【中文标题】在 Django Rest Framework 中生成 OpenAPI Schema:更新视图集中的 URL 关键字【英文标题】:Generating OpenAPI Schema in Django Rest Framework: URL Keyword in Update ViewSet 【发布时间】:2021-01-13 09:12:05 【问题描述】:我正在尝试做一些应该非常直截了当的事情,但我遇到了一个我无法正面或反面的问题。我希望有人能帮我解决这个问题。
我已经使用 DRF 创建了一些 API 端点。自然地,我使用 django_rest_framework.generics 构建了 Create、Update、Retrieve 和 Delete 端点。我需要从 CreateAPIView 和 UpdateAPIView 上的 ViewSet 向序列化程序发送一些额外的数据。为此,我在这些 ViewSet 上扩展了 get_serializer_context()
方法。
我现在正在尝试为这些端点创建 OpenAPI 文档。但是,当我在 manage.py 中运行 generateschema
时,它会返回错误。此错误发生在我扩展 get_serializer_context()
方法的每个 UpdateAPIViews 中。此错误的示例如下所示。
AssertionError: Expected view UpdateStaffViewSet to be called with a URL keyword argument named "staff_id". Fix your URL conf, or set the `.lookup_field` attribute on the view correctly.
当然,我们会认为我弄错了 URL 关键字或 lookup_field,正如错误所述。除非我正在查看一些明显的东西,否则我就是看不出问题所在。在使用 curl 或 postman 进行测试时,这些端点可以完美运行。我知道如果我删除扩展的get_serializer_context()
方法,generateschema
命令可以正常工作。 (但是使用 postman/curl 的测试会失败。)为什么这种扩展方法很重要!?
urls.py
url_patterns = [
path('v1/staff/retrieve/<int:staff_id>/', RetrieveStaffViewSet.as_view()),
path('staff/update/<int:staff_id>/', UpdateStaffViewSet.as_view()),
...
]
视图集
class UpdateRetrieveBase:
serializer_class = StaffSerializer
queryset = Staff.objects.select_related('user')
lookup_url_kwarg = 'staff_id'
lookup_field = 'pk'
class UpdateStaffViewSet(UpdateRetrieveBase, UpdateAPIView):
def get_serializer_context(self):
context = super().get_serializer_context()
context['validation_refs'] = get_validation_refs(staff=self.get_object())
return context
class RetrieveStaffViewSet(UpdateRetrieveBase, RetrieveAPIView):
pass
【问题讨论】:
【参考方案1】:好吧,毕竟,我找到了自己的答案。我会把它贴在这里以防其他人也被难住了。
由于generateschema
命令运行测试但不包含 URL kwargs,我们不能在视图集中调用get_object()
。测试必须考虑到这一点,但不考虑我们可能会在其他任何地方调用该方法。为了在我的特殊情况下解决这个问题,我编辑了代码。
视图集
class UpdateAEAContractViewSet(UpdateRetrieveBase, UpdateAPIView):
def get_serializer_context(self):
context = super().get_serializer_context()
contract_id = self.kwargs.get(self.lookup_url_kwarg)
context['validation_refs'] = get_validation_refs(contract_id=contract_id)
return context
验证参考子作业
def get_validation_refs(staff_id=None):
staff = Staff.objects.get(pk=staff_id) if staff_id else None
...
【讨论】:
以上是关于在 Django Rest Framework 中生成 OpenAPI Schema:更新视图集中的 URL 关键字的主要内容,如果未能解决你的问题,请参考以下文章