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!
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)
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)
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.