【问题标题】:Django Rest required parameters in URLURL中的Django Rest所需参数
【发布时间】:2016-09-25 21:00:19
【问题描述】:

我正在使用 django rest 框架。 这是我的代码:

urls.py:

urlpatterns = [
    url(r'^users/show', UserShow.as_view()),
]

view.py:

class UserShow(ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_queryset(self):
        queryset = User.objects.all()
        username = self.request.query_params.get('username', None)
        user_id = self.request.query_params.get('user_id', None)
        if username is not None:
            queryset = queryset.filter(username=username)
        if user_id is not None:
            queryset = queryset.filter(pk=user_id)
        return queryset

我想从 url 中获取值,如下所示: /users/show?user_id=1/users/show?username=mike

user_idusername 必须是必需参数。 如何在基于类的视图中控制它?

如果我使用错误的参数名称/users/show?user111name=mike 或简单的/users/show 发送请求,则使用我的代码,视图当然会以queryset = User.objects.all() 响应我并列出所有用户。我不需要那个。如果需要的参数是None 404 响应,我需要。

我可以通过基于函数的视图获得所需的结果:

@api_view(['GET'])
def users(request):
    if request.method == 'GET':
        queryset = User.objects.all()
        username = request.GET.get('username', None)
        user_id = request.GET.get('user_id', None)

        if username is not None:
            queryset = queryset.filter(username=username)
        elif user_id is not None:
            queryset = queryset.filter(pk=user_id)
        else:
            return Response({"status": "required field not found."},
                            status=status.HTTP_404_NOT_FOUND)

        if not queryset.exists():
            return Response({"status": "not found."},
                            status=status.HTTP_404_NOT_FOUND)

        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

但是如何使用基于 generic 类的视图来做到这一点?

【问题讨论】:

  • 您能解释一下为什么您使用 ListAPIView 来获取 single 对象吗?有一个专门用于此类用途的 RetrieveAPIView,此外,您可以将用户名或 id 用作 url 的一部分而不是查询..

标签: python django django-rest-framework django-class-based-views


【解决方案1】:
class UserIdRetrieve(RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

class UserUsernameRetrieve(UserIdRetrieve):
     lookup_field = 'username'

在网址中:

urlpatterns = [
    url(r'^users/(?P<pk>\d+)/', UserIdRetrieve.as_view()), 
    url(r'^users/by-username/(?P<username>\w+)/', UserUsernameRetrieve.as_view())
]

如果你的 url 结构是必须的,对上面的小改动:

class UserIdRetrieve(RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get_object(self):
        queryset = self.filter_queryset(self.get_queryset())

        if 'username' in self.request.query_params:
            filter_kwargs = {'username': self.request.query_params['username']}
        elif 'user_id' in self.request.query_params:
             filter_kwargs = {'id': self.request.query_params['user_id']}
        else:
            raise Http404('Missing required parameters')

        obj = get_object_or_404(queryset, **filter_kwargs)

        # May raise a permission denied
        self.check_object_permissions(self.request, obj)

        return obj

在网址中:

urlpatterns = [
    url(r'^users/show', UserRetrieve.as_view())
]

【讨论】:

  • 我正在使用ListAPIView,因为RetrieveAPIView 需要pk 作为参数,但在我的情况下,由于使用query_params,我没有以经典的django 方式从url 获取它。当然你的变种会起作用,但是再看一下所需的 url 格式,这不是我需要的。
  • 添加了与您的 url 结构相匹配的版本
【解决方案2】:
class UserShow(ListAPIView):

    queryset = User.objects.all()
    serializer_class = UserSerializer

    def filter_queryset(self, queryset):
        username = self.request.query_params.get('username', None)
        user_id = self.request.query_params.get('user_id', None)

        if username is not None:
            queryset = queryset.filter(username=username)
        if user_id is not None:
            queryset = queryset.filter(pk=user_id)
        return queryset

    def list(self,request,*args,**kwargs):
        username = self.request.query_params.get('username', None)
        user_id = self.request.query_params.get('user_id', None)
        if not (username or user_id):
            return Response({"status": "Required field not found."},
                                        status=status.HTTP_404_NOT_FOUND)
        return super(UserShow, self).list(request,*args,**kwargs)

【讨论】:

  • 它正在工作,但还有更多 DRY 方法吗?无论如何,我现在将您的答案标记为解决方案。
  • ListAPIView 不应用于检索单个实例
猜你喜欢
  • 1970-01-01
  • 2021-07-24
  • 2016-02-07
  • 1970-01-01
  • 2016-01-05
  • 1970-01-01
  • 2017-01-09
  • 2014-06-28
  • 1970-01-01
相关资源
最近更新 更多