0

I am trying to implement filter api in django rest. Something like -

localhost:8000/api/v1/users/[email protected]/

So it should search for user with the passed filter and return the result.But currently it is returning all user.

URLS.py

    url(r'^api/v1/users/$',   UserViews.UserList.as_view(), name='userlist_view'),
    url(r'^api/v1/users/(?P<email>.+)/$', UserViews.UserList.as_view(), name='userList_view'),
    url(r'^api/v1/users/(?P<pk>[0-9]+)/$', UserViews.UserDetail.as_view(), name='userdetail_view'),

UserViews.py

class UserList(generics.ListAPIView):
    """
    List all users, or create a new user.
    """
    lookup_url_kwarg = "email"

    def get(self, request, format=None):
        if request.user.is_authenticated():
            users = User.objects.all()
            serializer = UserSerializer(users, many=True)
            return Response(serializer.data)
        return Response("User is not authenticated.", status=status.HTTP_400_BAD_REQUEST)

    def post(self, request, format=None):

        valid_paylaod, msg = UserListRepository.validations_create_user(request.data)
        if not valid_paylaod:
            return Response(msg, status=status.HTTP_400_BAD_REQUEST)

        result = UserListRepository.create_user_repo(request)

        if not result.success:
            return Response(str(result.msg), status=result.status )

        return Response(UserSerializer(result.data).data, status=result.status)

   def get_queryset(self):
    # It restricts the userlist by retunning users having emails passed in uery param
    user = self.request.user
    if user.is_authenticated():
         if 'email' in self.request.query_params:
            email = self.request.query_params.get('email', None)
            users = User.objects.get(email= email)
            if not users:
                return Response( "User Not found", status=status.HTTP_404_NOT_FOUND)
            else:
                return Response(UserSerializer(User.objects.all()).data, status.HTTP_200_OK, users)
        else:
            return Response(UserSerializer().data, status=result.status)
    else:
        return Response("User is not authenticated.", status=status.HTTP_400_BAD_REQUEST)

Can some one tell why the request is not going to get_queryset() method and going to get() of UserList method. On removing get method, the request goes to get_queryset(self) method. On debugging, I found that I get valid Response before return statement -

(Pdb) UserSerializer(result.data).data
{'parent_id': 2, 'id': 31, 'group_id': '4', 'last_name': 'user',         'email': '[email protected]', 'organization_id': 0, 'first_name':  'agency22'}

But Still in APi response, I get following error :

Internal Server Error: /api/v1/users/
 Traceback (most recent call last):
 File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
 File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
Fi e "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
 File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/generics.py", line 201, in get
return self.list(request, *args, **kwargs)
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/mixins.py", line 43, in list
if page is not None:
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/serializers.py", line 674, in data
ret = super(ListSerializer, self).data
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-    packages/rest_framework/serializers.py", line 614, in to_representation
self.child.to_representation(item) for item in iterable
 File "/Users/richagupta/VirtualEnvs/py35/lib/python3.5/site-  packages/django/template/response.py", line 173, in __iter__
raise ContentNotRenderedError('The response content must be '
 django.template.response.ContentNotRenderedError: The response content          must be rendered before it can be iterated over.

I am not clear why . API URL I am hitting is : localhost:8000/api/v1/[email protected]

2
  • self.lookup_url_kwarg, why self here? Commented Apr 12, 2016 at 9:31
  • We can even try following :def get_queryset(self,request): # It restricts the userlist by returning users having emails passed in uery param email = self.request.query_params.get('email',None) return User.objects.filter(email=email) Issue is, request doesn't go to that method. Commented Apr 12, 2016 at 9:39

4 Answers 4

2

The problem is that you are overriding the get method of ListAPIView. This method is called by a GET request. The default implementation of get calls the list method of ListModelMixin and there get_queryset gets called:

def list(self, request, *args, **kwargs):
    queryset = self.filter_queryset(self.get_queryset())

    page = self.paginate_queryset(queryset)
    if page is not None:
        serializer = self.get_serializer(page, many=True)
        return self.get_paginated_response(serializer.data)

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

If you override this method you have to call get_queryset yourself. If you just want to check if the user is authenticated and then call the default list method you can do it like this:

  def get(self, request, format=None):
        if request.user.is_authenticated():
            return super(UserList, self).get(request, format)
        return Response("User is not authenticated.", status=status.HTTP_400_BAD_REQUEST)
Sign up to request clarification or add additional context in comments.

1 Comment

I am able to call me get_query() method by removing get() method. Still I am not able to resolve the error mentioned in the question (above)
1

I'm confused by the UrlConf:

url(r'^api/v1/users/$', UserViews.UserList.as_view(), name='userlist_view'),
url(r'^api/v1/users/(?P<email>.+)/$', UserViews.UserList.as_view(), name='userList_view'),
  • First one is for localhost:8000/api/v1/users/
  • Second one is for localhost:8000/api/v1/users/[email protected]/ not localhost:8000/api/v1/users/[email protected]/, this is a query parameter not kwargs, check this if you want to use query parameter

    class UserList(generics.ListAPIView):
    """
    List all users, or create a new user.
    """
    lookup_url_kwarg = "email"
    serializer_class = UserSerializer
    
    def post(self, request, format=None):
    
        valid_paylaod, msg = UserListRepository.validations_create_user(request.data)
        if not valid_paylaod:
            return Response(msg, status=status.HTTP_400_BAD_REQUEST)
    
        result = UserListRepository.create_user_repo(request)
    
        if not result.success:
            return Response(str(result.msg), status=result.status )
    
        return Response(UserSerializer(result.data).data, status=result.status)
    def get_queryset(self):
    """
    It restricts the userlist by return users having emails passed in query param
    """
        queryset = Users.objects.all()
        email = self.request.query_params.get('email', None)
        if email is not None:
            queryset = queryset.filter(email=email)
        return queryset
    

3 Comments

I am able to call me get_query() method by removing get() method. Still I am not able to resolve the error mentioned in the question(above)
Because you are overriding the default behaviour, you are use a generic view which give you get() method by default, stop overriding get() and will get what you want but do some change on get_queryset()
And get the Authorizing code away from the View class django-rest-framework.org/api-guide/authentication/…
1

It looks like you are using Response from django instead of django-rest-framework.

You have to import Response from rest_framework.response

from rest_framework.response import Response

Comments

1

In Django rest framework there is a proper specification of how to use filters. So your user class would look like.

class UserList(generics.ListAPIView):
    """
    List all users, or create a new user.
    """
    lookup_url_kwarg = "email"
    serializer_class = UserSerializer

    def get(self, request, format=None):
        if request.user.is_authenticated():
            users = User.objects.all()
            serializer = UserSerializer(users, many=True)
            return Response(serializer.data)
        return Response("User is not authenticated.", status=status.HTTP_400_BAD_REQUEST)

    def post(self, request, format=None):

        valid_paylaod, msg = UserListRepository.validations_create_user(request.data)
        if not valid_paylaod:
            return Response(msg, status=status.HTTP_400_BAD_REQUEST)

        result = UserListRepository.create_user_repo(request)

        if not result.success:
            return Response(str(result.msg), status=result.status )

        return Response(UserSerializer(result.data).data, status=result.status)

    def get_queryset(self):
        email = self.request.query_params.get('email', None)
        return User.objects.filter(email=email)

or you can try without get_queryset . The link would change , updated link is :

localhost:8000/api/v1/users/[email protected]/

and the updated code is

class UserList(generics.ListCreateAPIView):
        """
        List all users, or create a new user.
        """
        lookup_url_kwarg = "email"
        serializer_class = UserSerializer

        def get(self, request, email,format=None):
            if request.user.is_authenticated():
                user_details = User.objects.filter(email=email)
                serializer = UserSerializer(user_details, many=True)
                return Response(serializer.data, status=status.status.HTTP_200_OK)
            return Response("User is not authenticated.", status=status.HTTP_400_BAD_REQUEST)

        def post(self, request, format=None):

            valid_paylaod, msg = UserListRepository.validations_create_user(request.data)
            if not valid_paylaod:
                return Response(msg, status=status.HTTP_400_BAD_REQUEST)

            result = UserListRepository.create_user_repo(request)

            if not result.success:
                return Response(str(result.msg), status=result.status )

            return Response(UserSerializer(result.data).data, status=result.status)

2 Comments

Well there are two apis-
@RichaGupta I have updated the code , as you are using two APIs one is GET and other POST , so you need to use ListCreateAPIView that user ListModelMixin (has list method that can be used on place of get and that would be more meaningful),CreateModelMixin (has create method that can be used on place of post method and would be more meaningful) and GenericAPIView (has get and post methods that's being inherited currently).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.