2

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 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

4 Comments

thanks @mohammadjh I do some change, I update the request but this url dont work for me url(r'^users/(?P<username>[a-zA-Z0-9]+)$', UserViewSet.as_view({'get': 'retrieve'})), any idea about why? I try this url 127.0.0.1:8000/cpuProjects/adr
Page no found (404) Using the URLconf defined in drf_demo.urls, Django tried these URL patterns, in this order: ^cpuProjects/$ ^cpuProjects/(?P<project_name>[a-zA-Z0-9]+)$ The current URL, cpuProjects/ad/, didn't match any of these. @mohammadjh
Try 127.0.0.1:8000/cpuProjects/cpuProjects/adr
now work! I restart the server, and clean the cache and everything work, thanks so much. Let me ask another question, sorry but I am new, I read de documentation for Django rest framework, but for me if not enough clear, if now I want to try URL like this 127.0.0.1:8000/cpuProjects/cpuProjects/adr/pendding or 127.0.0.1:8000/cpuProjects/cpuProjects/adr/sending how to read whatever string I put behind the cpu name /adr/ I try with lookup_field and ` lookup_url_kwarg` a have a print in retrieve function and I see this {'name_proj': u'adr/pedding'}
2

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)

Comments

1

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)

1 Comment

thanks @pleasedontbelong work perfectly but I still have some dudes, if I change the name of params, like that def retrieve(self, request, name=None): the function fail, so the function expecting a primary key ,although I use the pk params like this cursor.execute('SELECT * FROM proj_cpus WHERE project = %s', [pk]) so it is correct? and other think if I want to get more that one name How is the URL http://127.0.0.1:8000/cpuProjects/name1, name2 I try this but don't work. I update my request with the new code

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.