从另一个视图调用ViewSet方法

时间:2018-07-03 08:09:44

标签: django django-rest-framework

我有一个带有Django REST框架API的移动应用程序,并且我调用了许多ModelViewSet来检索数据。我遇到了性能问题,因为我需要在用户登录后调用很多路由,并且我希望保留REST逻辑,但是在登录后还返回登录响应中所有视图集的内容(保留其过滤器)。

是否可以从另一个视图(视图集或APIView)调用ModelViewset list()?

我在SO上找到的唯一答案就是要做类似的事情

class ContentGenerator(APIView):

    def get(self, request, format=None):
         data = MyModelViewSet.as_view({'get': 'list'})(request).data

         return Response({'data': data})

但是不支持

Exception Value: The `request` argument must be an instance of `django.http.HttpRequest`, not `rest_framework.request.Request`

还有其他解决方法吗?

3 个答案:

答案 0 :(得分:2)

经过一些研究,看起来在其他视图中重用该请求可能会有副作用,因此DRF并未正式支持它。这很hacky,但是如果您知道自己在做什么,这是一个解决方案。

data = MyModelViewSet.as_view({'get': 'list'})(request._request).data

答案 1 :(得分:0)

就我而言,足以做到这一点:

data = MyClassViewSet()
for i in data.queryset:
   # Then you can access to any field of your model like this:
   i.id
   i.name
   ...
   # And do what you need

但这显然仅适用于{'get':'list'}

如果该方法是额外的操作(例如,products_filtered_by_user),则可以执行以下操作:

data = MyClassViewSet()
data.products_filtered_by_user(request,user=kwargs['user_id'])
if data.code == 200:
    response_data = data.response_data

答案 2 :(得分:0)

我用两种方法解决了这个问题。假设我有一个 viewset B 和一个 B.my_action,并且我想从 A 调用 B.my_actioncode w/in BViewSet 处理特定的 id,例如用户 ID、产品 ID 等

第一种方式

@action(detail=True, methods=['post']) def my_action(self, request, pk=None): try: # works when you call from web UI, through router # automatically you have one specific view corresponding # to specific id e.g. user id, product id etc instance = self.get_object() except AttributeError as ae: # here you don't have a specific view instantiated # and you have many ids e.g. user ids, product ids etc # pick one id instance = MyModelObject.objects.get(id=pk) # rest of code as is, no change

code w/in e.g. AView.utils.py that calls BViewSet.my_action

request

AView 下面是调用 AView 时传递给 from django.http import HttpRequest data = BViewSet(detail=True) new_request = HttpRequest() new_request.data = any_data_I_need_to_pass # e.g. request.data ret = data.my_action(new_request, pk=request.data['id']) return ret 的请求 通过网络用户界面。

my_action

第二种方式

我将 my_action 功能与 code w/in BViewSet 调用分离,即

@action(detail=True, methods=['post']) def my_action(self, request, pk=None): instance = self.get_object() ret = my_action_server(instance, request.data) return Response(data=ret) def my_action_server(instance, data): # all code comes here return result

code w/in Aview

# import my_action_server as needed # call my_action_server # AView should provide everything needed

class ExerciseGridWidget extends StatelessWidget {
  final String text;
  final String subText;
  const ExerciseGridWidget(
    this.text,
    this.subText, {
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Row(
      crossAxisAlignment: CrossAxisAlignment.end,
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        BodyText2(text),
        SubTitleText2(
          ' ' + this.subText,
        ),
      ],
    );
  }
}