using django rest framework to return info by name

2019-02-26 06:25发布

I am using Django rest framework and I create this class to return all the name of project

class cpuProjectsViewSet(viewsets.ViewSet):
  serializer_class = serializers.cpuProjectsSerializer

  def list(self, request):
    all_rows = connect_database()
    name_project = [] 
    all_projects = []
    for item_row in all_rows:
      name_project.append(item_row['project'])
      name_project = list(sorted(set(name_project)))
    for i in range(0, len(name_project)):
      all_projects.append({'project' : str(name_project[i])})

    serializer = serializers.cpuProjectsSerializer(instance=all_projects, many=True)
    return Response(serializer.data)

my URL is like that http://127.0.0.1:8000/cpuProjects/ this return all the projects, buy If now I want a particular project, Have I to create a new class?? if I want to use the same URL ... for example http://127.0.0.1:8000/cpuProjects/ => return all project http://127.0.0.1:8000/cpuProjects/nameProject => return a particular project.

class cpuProjectsViewSet(viewsets.ViewSet):
  serializer_class = serializers.cpuProjectsSerializer
  lookup_field = 'project_name'

  def retrieve(self, request, project_name=None):
    try:
      opc = {'name_proj' : project_name }
      all_rows = connect_database(opc)
    except KeyError:
        return Response(status=status.HTTP_404_NOT_FOUND)
    except ValueError:
        return Response(status=status.HTTP_400_BAD_REQUEST)
    serializer = serializers.cpuProjectsSerializer(instance=all_rows, many=True)
    return Response(serializer.data)

Is it possible to do in the same class? I try to use retrieve method but the need an ID of the project, no the name right?

thanks in advance!

3条回答
别忘想泡老子
2楼-- · 2019-02-26 06:51

If you want to use the same class you can use a viewset and define a list() and retrieve() methods

check http://www.django-rest-framework.org/api-guide/viewsets/ the first example is doing that

from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
    """
    A simple ViewSet for listing or retrieving users.
    """
    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data)
查看更多
戒情不戒烟
3楼-- · 2019-02-26 06:54

You need to add lookup_field in view class. Suppose, you want to get user by username you need to add lookup_field = 'username'.

Example:

from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):

    lookup_field = 'username'

    def list(self, request):
        queryset = User.objects.all()
        serializer = UserSerializer(queryset, many=True)
        return Response(serializer.data)

    def retrieve(self, request, username=None):
        queryset = User.objects.all()
        user = get_object_or_404(queryset, username=username)
        serializer = UserSerializer(user)
        return Response(serializer.data)

Now your url will be

url(r'^users/$', UserViewSet.as_view({'get': 'list'})),
url(r'^users/(?P<username>[a-zA-Z0-9]+)$', UserViewSet.as_view({'get': 'retrieve'})),

Now http://127.0.0.1:8000/users/ will return all users and http://127.0.0.1:8000/users/username will return particular user details.

You can learn more about lookup_field from Django REST framework.

查看更多
手持菜刀,她持情操
4楼-- · 2019-02-26 07:04

One does not use raw queries unless absolutely needed and even then, there isn't a need to manually connect to the database because you have easy access to a connection object. Overall, your retrieve method can be improved as follows:

def retrieve(self, request, pk=None):
    queryset = CpuProject.objects.all()
    cpu = get_object_or_404(queryset, pk=pk)
    serializer = serializers.cpuProjectsSerializer(cpu)
    return Response(serializer.data)

Much shorter and easier to read. But Even this is not really needed If you use a ModelViewset! Then the default retrieve method will take care of this for you. So your viewset reduces to

class cpuProjectsViewset(viewsets.ModelViewSet):
    serializer_class =serializer = serializers.cpuProjectsSerializer
    queryset = CpuProject.objects.all()

You don't need a retrieve method here!!

But I see that you are trying to retrieve a particular CpuProject item by it's name (rather than using it's PK). For that you need to add a route

from rest_framework.decorators import detail_route, list_route
@detail_route(url_path='(?P<slug>[\w-]+)')
def get_by_name(self, request, pk=None,slug=None):

    queryset = CpuProject.objects.all()
    cpu = get_object_or_404(queryset, name=slug)
    serializer = serializers.cpuProjectsSerializer(cpu)
    return Response(serializer.data)
查看更多
登录 后发表回答