【问题标题】:Django rest framework allow lookup_field to have several optionsDjango rest 框架允许lookup_field 有几个选项
【发布时间】:2018-04-16 03:10:55
【问题描述】:

我目前正在学习如何为我的公司构建 API。我已经很久没有这样做了,所以我现在基本上是一名初级开发人员。

按照一些教程,我使用基于类的视图启动并运行了我的 API。

我们使用硬件进行科学测量,它基于“运行”、“运行属性”和“腔室”。

对于 URL,我希望允许基于几个不同的关键字进行查找。因此,如果他们访问“www.example.com/api/runs_list”,API 将显示所有已完成的运行和已登录用户的会议室。

我想允许搜索特定的运行或按腔室。因此,如果他们想在 2017-11-02T18:20:24Z 开始运行,他们可以访问“www.example.com/api/2017-11-02T18:20:24Z”并获取与相关的 JSON 数据运行。

或者,如果他们访问“www.example.com/api/chamber_34-A”,他们将获得该室迄今为止执行的所有运行。

我查看了lookup_field 和lookup_url_kwargs,但它似乎只允许一个选项(我现在将其设置为chamber)。

这是我所拥有的:

urls.py

from django.conf.urls import url
from django.contrib import admin

from company.api.views import (
    RunPropertiesListAPIView,
    RunPropertiesDetailAPIView,
    RunsDetailAPIView,
    RunsListAPIView,
)

urlpatterns = [
    url(r'^runs_list/$', RunsListAPIView.as_view(), name='runs_list'),
    url(r'^properties_list/$', RunPropertiesListAPIView.as_view(), 
        name='properties_list'),
    url(r'^runs_list/(?P<chamber>\d+)/$', RunsDetailAPIView.as_view(), 
        name='runs_list_detail'),
    url(r'^properties_list/(?P<chamber>\d+)/$', 
        RunPropertiesDetailAPIView.as_view(), name='properties_list_detail'),
]

这里是 serializers.py

from rest_framework.serializers import ModelSerializer

from company.company_import.models import (
    RunProperties,
    Runs,
)

class RunsSerializer(ModelSerializer):
        class Meta:
            model = Runs
            fields = [
                'id',
                'chamber',
                'start_time',
                'end_time',
                'step_time'
            ]

class RunPropertiesSerializer(ModelSerializer):
        class Meta:
            model = RunProperties
            fields = [
                'id',
                'runs',
                'property_name',
                'property_value'
            ]

这里是views.py

from rest_framework.generics import ListAPIView, RetrieveAPIView

from company.company_import.models import (
    RunProperties,
    Runs,
)

from company.company_import.api.serializers import (
    RunPropertiesSerializer,
    RunsSerializer,
)

class RunsListAPIView(ListAPIView):
    queryset = Runs.objects.all()
    serializer_class = RunsSerializer

class RunPropertiesListAPIView(ListAPIView):
    queryset = RunProperties.objects.all()
    serializer_class = RunPropertiesSerializer

class RunsDetailAPIView(RetrieveAPIView):
    queryset = Runs.objects.all()
    serializer_class = RunsSerializer
    lookup_field = 'chamber'
    lookup_url_kwarg = 'chamber'

class RunPropertiesDetailAPIView(RetrieveAPIView):
    queryset = RunProperties.objects.all()
    serializer_class = RunPropertiesSerializer

我尝试过的:

在 urls.py 上

(using a | to allow two options for RegEx)(didn't seem to work)

url(r'^runs_list/(?P<chamber>\d+)|(?P<start_time>\d+)/$', 
        RunsDetailAPIView.as_view(), 
        name='runs_list_detail'),

关于views.py

(Using python "or" to see if allowed for different options, didn't work)

class RunsDetailAPIView(RetrieveAPIView):
    queryset = Runs.objects.all()
    serializer_class = RunsSerializer
    lookup_field = 'chamber' or 'start_time' (didn't work)
    lookup_url_kwarg = 'chamber' or 'start_time' (didn't work)

(Using a list of strings to see if it allowed for different options, didn't 
work)

queryset = Runs.objects.all()
    serializer_class = RunsSerializer
    lookups = ['chamber', 'start_time'] (didn't work)
    lookup_field = lookups (didn't work)
    lookup_url_kwarg = lookups (didn't work)

目前我已将其默认设置为分庭,但我真的很想启用特定且多样化的搜索查找。

【问题讨论】:

    标签: python django django-rest-framework django-views


    【解决方案1】:

    与其试图找出您在 URL 本身中捕获的内容,不如尝试捕获传递给 URL 的任何 kwarg,然后在您的视图中找出如何处理它。

    您的 URL 模式可能如下所示:

    url(r'^runs_list/(?P<search_term>\d+)/$', 
        RunsDetailAPIView.as_view(), 
        name='runs_list_detail'),
    

    然后在你的视图中解析search_term

    def get_object(self):
        search_term = self.kwargs['search_term']
        ...
    

    例如,您可以使用您的 search_term 进行一些 Q 语句:https://docs.djangoproject.com/en/1.11/topics/db/queries/#complex-lookups-with-q-objects

    Runs.objects.filter(
        Q(chamber = search_term) | Q(start_time = search_term)
    )
    

    根据您的用例、搜索字段和环境,您还可以考虑制作SearchVectors:https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/search/#searchvector

    或者你甚至可以简单地 filter 你的查询集使用 try/except 块。要点是从您的 URL 中获取 kwarg 并在您的 get_object 函数中使用它,而不是试图在 URL 本身中弄清楚它。


    以上所有内容都适用于基础 Django;不需要 DRF。由于您正在使用 Django Rest Framework,因此您可能还对 django-filters 包感兴趣:

    http://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend

    【讨论】:

    • 非常感谢@souldeux,最终 django-filters 包解决了我的问题以及我想添加的其他一些功能(例如对象权限过滤器)。您的回答帮助很大!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 2021-07-31
    相关资源
    最近更新 更多