【问题标题】:using django rest framework to return info by name使用 django rest 框架按名称返回信息
【发布时间】:2017-02-05 08:44:47
【问题描述】:

我正在使用 Django rest 框架,我创建了这个类来返回项目的所有名称

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)

我的 URL 是这样的 http://127.0.0.1:8000/cpuProjects/ 这个返回所有项目,购买 如果现在我想要一个特定的项目,我是否要创建一个新类?如果我想使用相同的 URL ...例如 http://127.0.0.1:8000/cpuProjects/ => 返回所有项目 http://127.0.0.1:8000/cpuProjects/nameProject => 返回一个特定的项目。

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)

可以在同一个班级做吗?我尝试使用检索方法,但需要项目的 ID,没有名称对吗?

提前致谢!

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    除非绝对需要,否则不会使用原始查询,即使那样,也不需要手动连接到数据库,因为您可以轻松访问连接对象。总体而言,您的检索方法可以改进如下:

    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)
    

    更短更容易阅读。但是,如果您使用 ModelViewset,即使这也不是真正需要的!然后默认的检索方法将为您处理这个问题。所以你的视图集减少到

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

    这里不需要retrieve方法!!

    但我看到您正在尝试通过名称检索特定的 CpuProject 项目(而不是使用它的 PK)。为此,您需要添加一条路线

    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)
    

    【讨论】:

      【解决方案2】:

      您需要在视图类中添加lookup_field。假设你想通过用户名获取用户,你需要添加lookup_field = 'username'

      例子:

      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)
      

      现在您的网址将是

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

      现在http://127.0.0.1:8000/users/ 将返回所有用户,http://127.0.0.1:8000/users/username 将返回特定用户详细信息。

      您可以通过Django REST framework了解更多关于lookup_field的信息。

      【讨论】:

      • 谢谢@mohammadjh 我做了一些改变,我更新了请求,但是这个网址对我不起作用 url(r'^users/(?P[a-zA-Z0-9]+ )$', UserViewSet.as_view({'get': 'retrieve'})),知道为什么吗?我试试这个网址127.0.0.1:8000/cpuProjects/adr
      • 找不到页面 (404) 使用 drf_demo.urls 中定义的 URLconf,Django 按以下顺序尝试了这些 URL 模式:^cpuProjects/$ ^cpuProjects/(?P[a-zA -Z0-9]+)$ 当前 URL,cpuProjects/ad/,与其中任何一个都不匹配。 @mohammadjh
      • 试试127.0.0.1:8000/cpuProjects/cpuProjects/adr
      • 现在开始工作!我重新启动服务器,清理缓存,一切正常,非常感谢。让我再问一个问题,对不起,但我是新手,我阅读了 Django rest 框架的文档,但对我来说,如果不够清楚,如果现在我想尝试像 127.0.0.1:8000/cpuProjects/cpuProjects/adr/pendding127.0.0.1:8000/cpuProjects/cpuProjects/adr/sending 这样的 URL 如何读取任何字符串我把 cpu 名称 /adr/ 放在后面我尝试使用 lookup_field 和 `lookup_url_kwarg` 在检索函数中有一个打印,我看到了这个 {'name_proj': u'adr/pedding'}
      【解决方案3】:

      如果你想使用同一个类,你可以使用一个视图集并定义一个 list() 和 retrieve() 方法

      检查http://www.django-rest-framework.org/api-guide/viewsets/第一个例子就是这样做

      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)
      

      【讨论】:

      • 感谢@pleasedontbelong 工作完美,但我仍然有一些家伙,如果我更改参数的名称,就像def retrieve(self, request, name=None): 函数失败,所以函数需要一个主键,虽然我使用 pk像这样的参数cursor.execute('SELECT * FROM proj_cpus WHERE project = %s', [pk]) 所以它是正确的吗?其他人认为,如果我想获得更多的名字,那么 URL http://127.0.0.1:8000/cpuProjects/name1, name2 是怎样的?我试试这个,但没有用。我用新代码更新我的请求
      猜你喜欢
      • 2018-02-13
      • 2020-10-11
      • 2021-09-26
      • 1970-01-01
      • 2021-10-16
      • 1970-01-01
      • 1970-01-01
      • 2017-08-21
      • 2014-10-16
      相关资源
      最近更新 更多