【问题标题】:DRF change default viewset's lookup_field for custom actionDRF 更改默认视图集的 lookup_field 以进行自定义操作
【发布时间】:2019-06-06 12:38:05
【问题描述】:

如何更改 DRF Viewset 中自定义操作的默认查找参数? 这是我的视图集(简化)

class InvitationViewSet(MultiSerializerViewSet):   
    queryset = Invitation.objects.all()  

    @action(
        detail=False,
        #url_path='accept-invitation/<str:key>/',
        #lookup_field='key'
    )
    def accept_invitation(self, request, key=None):
        invitation = self.get_object()
        with legal_invitation(invitation):
            serializer = self.get_serializer(invitation)
            invitation.accepted = True
            invitation.save()
        return Response(serializer.data)

我想当用户输入像/invitations/accept-invitation/abccba 这样的url,其中abccba 是一个随机令牌字符串。 key - 是邀请模型中的一个独特字段。我知道我可以设置每个视图集lookup_field='key',但我希望所有其他操作仍然使用默认的lookup_field='pk'。我怎样才能实现我想要的?

【问题讨论】:

  • @dirkgroten 有内置视图集的操作,例如 retrievecreate 等。所以我的意思是所有需要 detail=True 的操作 - 仍然使用 pk 作为默认搜索值.
  • 你不能。为它创建一个单独的视图。 ViewSet 中的所有操作共享相同的lookup_field。注意:url 是邀请/{lookup_key}/accept-invitation

标签: python django django-rest-framework


【解决方案1】:

您可以覆盖get_object() 方法来实现这一点。这是GenericAPIView 代码:

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

    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]}
    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_kwargget_object 函数中的 self.action 应该等于 accept_invitation(您正在装饰的函数的名称)。

但这里的问题是您正在使用带有detail=False 的动作装饰器,因此查找字段没有多大意义。我的方法适用于其中一个 cmets 中提到的常规详细路线:&lt;your_api_url&gt;/&lt;invitation-viewset-path&gt;/&lt;key&gt;/accept-invitation/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    相关资源
    最近更新 更多