使用多个字段创建自定义Django REST URL

时间:2015-09-22 20:13:29

标签: python django django-rest-framework

我正在构建一个与Django数据库对话的SMS API,这是一个数百人的联系信息列表。字段如下:名字,姓氏,电话号码和职位。

我在本地服务器上使用此网址时收到回复:

http://localhost:8000/sources/id

我想要做的是使用此网址向同一个数据库发出请求:

http://localhost:8000/sources/first_name-last_name

我已经调查过有关字段查找的多个问题,但没有任何帮助。这是我的serializers.py的样子:

from rest_framework import serializers, viewsets
from text_source.models import Source

class SourceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Source
        fields = ('id','first_name','last_name','title','organization','city','cell_phone','office_phone')
        lookup_field = 'first_name'

class SourceViewSet(viewsets.ModelViewSet):
    queryset = Source.objects.all()
    serializer_class = SourceSerializer
    lookup_field = ('first_name')

我不确定使用/ first_name-last_name作为url的终点是最佳做法,但是,理论上我正在做的事情,它会起作用。

理想情况下,我希望有人在文本中输入FIRSTNAME LASTNAME并让API通过将全名连接到数据库中的ID来返回正确的信息。任何提示,以实现这一点将不胜感激。

urls.py

from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic.base import TemplateView
from django.contrib.auth.models import User

from rest_framework import routers, serializers, viewsets
from app import views
from app.serializers import SourceSerializer, SourceViewSet

router = routers.DefaultRouter()
router.register(r'sources', SourceViewSet)

urlpatterns = [

    url(r'^page/$', TemplateView.as_view(template_name='base.html')),

    url(r'^page/', include(router.urls)),

    url(r'^admin/', include(admin.site.urls)),

    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),

    url(r'^page/incoming/message$', views.incoming_message)
]

3 个答案:

答案 0 :(得分:1)

我会尝试做类似下面的例子。您可以将kwargs更改为您最终使用的任何内容。

<强> 串行器:

class SourceUrlField(serializers.HyperlinkedIdentityField):
    def get_url(self, obj, view_name, request, format):
        kwargs = {
            'first_name': obj.first_name,
            'last_name': obj.last_name
        }
        return reverse(view_name, kwargs=kwargs,
                       request=request, format=format)

class SourceSerializer(serializers.HyperlinkedModelSerializer):
    url = SourceUrlField("view_name")

    class Meta:
        model = Source
        fields = (
            'id',
            'url',
            'first_name',
            'last_name',
            'title',
            'organization',
            'city',
            'cell_phone',
            'office_phone',
        )

根据Joey的推理,如果可能,我会尽量避免使用first_namelast_name。但是,我刚刚向您展示的示例将适用于您选择使用的任何一个kwargs。

答案 1 :(得分:0)

我认为您可能会遇到/sources/first_name-last_name作为端点的问题,因为您永远无法保证名称的唯一性,而且名称也可能包含破折号。我建议将/sources/id(大概是/sources/)作为您的终点,并且只允许过滤。

您可以阅读in the DRF documentation了解有关过滤的更多详细信息,但基本示例(安装django-filter之后)将如下所示:

from rest_framework import filters, serializers, viewsets
from text_source.models import Source

class SourceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Source
        fields = ('id','first_name','last_name','title','organization','city','cell_phone','office_phone')


class SourceViewSet(viewsets.ModelViewSet):
    queryset = Source.objects.all()
    serializer_class = SourceSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ('first_name', 'last_name')

完成此操作后,您可以按/sources/?first_name=Bob&last_name=Dobbs行构建网址以执行搜索并返回ID。

另请注意,您的示例中有一个非常重要的错误。您将ViewSet上的lookup_field指定为('first_name')。这个确切的语法,因为元组中只有一个元素,通过将字符串'first_name'视为可迭代来产生非常多的不良副作用,创建一个类似('f', 'i', 'r', 's', 't', '_', 'n', 'a', 'm', 'e')的元组。为了防止这种情况,您希望使用的是('first_name', )。请注意尾随的逗号。

答案 2 :(得分:0)

您可以在运行时覆盖lookup_field,具体取决于您在GET参数中获得的属性。只要您只想定义一个视图和网址,就不能使用kwargs。

示例网址: -

/sources/?parameter=first_name&first_name='someone'

相应地更改您的视图集: -

class SourceViewSet(viewsets.ModelViewSet):
     queryset = Source.objects.all()
     serializer_class = SourceSerializer
     lookup_field = ('first_name')

     def initial(self, request, *args, **kwargs):
         parameter = request.data.get('parameter')
         self.lookup_field = parameter
         kwargs[parameter] = request.data.get(parameter)

         super(SourceViewSet, self).initial(request, *args, **kwargs)