3

J'utilise le cadre de repos django. Voici mon code:Django Rest paramètres requis dans l'URL

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 

Je veux obtenir des valeurs de l'URL comme ceci: /users/show?user_id=1 ou /users/show?username=mike .

Un paramètre user_id ou username doit être requis. Comment puis-je le contrôler dans les vues basées sur les classes?

Avec mon code si j'envoie la demande avec le mauvais nom de paramètre /users/show?user111name=mike ou simple /users/show la vue de réponse bien sûr moi avec queryset = User.objects.all() et répertorie tous les utilisateurs. Je n'ai pas besoin de ça. J'ai besoin si les paramètres requis sont None réponse avec 404.

Je me nécessaire résultat avec vue sur la base fonction:

@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) 

Mais comment puis-je faire avec vues génériques sur la base de classe?

+0

Vous s hould jeter un oeil à http://stackoverflow.com/questions/36505792/drf-base-viewset-for-query-param-validation – trinchet

+0

Pourriez-vous m'expliquer pourquoi vous utilisez ListAPIView pour obtenir un objet * simple *? Il y a un RetrieveAPIView dédié pour une telle utilisation, plus vous pouvez avoir le nom d'utilisateur ou l'id utilisé dans le cadre de l'url pas question .. – Jerzyk

Répondre

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

class UserUsernameRetrieve(UserIdRetrieve): 
    lookup_field = 'username' 

et urls:

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

si la structure de votre URL est un must, petit changement ci-dessus:

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 

et urls:

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

J'utilise 'ListAPIView' car' RetrieveAPIView' nécessite 'pk' comme argument mais dans mon cas, je ne l'obtiens pas d'url de façon classique, en utilisant' query_params '. Bien sûr, votre variante fonctionnera, mais jetez un oeil au format d'URL requis à nouveau, ce n'est pas exactement ce dont j'ai besoin. – arstj

+0

a ajouté la version qui correspond à votre structure d'URL – Jerzyk

-1
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) 
+0

Ça marche mais y at-il plus de façon DRY? Quoi qu'il en soit, je vais marquer votre réponse comme solution pour l'instant. – arstj

+0

ListAPIView ne doit pas être utilisé pour récupérer une instance unique – Jerzyk