我有一个带有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`
还有其他解决方法吗?
答案 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_action
。 code 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,
),
],
);
}
}