在带有 json api 的 django rest 框架中使用 slug 而不是 ID
Posted
技术标签:
【中文标题】在带有 json api 的 django rest 框架中使用 slug 而不是 ID【英文标题】:Using the slug rather than ID in django rest framework with json api 【发布时间】:2019-07-12 02:56:50 【问题描述】:我的成员应用程序希望 JSON 响应包含模型 ID 的主键结果。我不想使用整数 ID,而是使用 slug。我知道在标准的 django 框架中你可以这样做:
from rest_framework import serializers
from .models import Page
class PageSerializer(serializers.ModelSerializer):
id = serializers.CharField(source='slug')
class Meta:
model = Page
fields = ('name','id',...etc )
但是,这在使用 json API 时不起作用 - 在我的回复中,我仍然有类似的东西
"data": [
"type": "pages",
"id": "2",
"attributes":
"name": "Some page name",
]
当我希望“id”字段类似于“some-page-name”(蛞蝓)时
这对于 json API 是不可能的。为清楚起见,上面等效的 json API 导入将是
from rest_framework_json_api import serializers
非常感谢
****添加****
为了帮助澄清我面临的问题,这里是一个使用标准 REST 框架的序列化程序。下面显示的所有属性都包含在 Page 模型中。
from rest_framework import serializers
from .models import Page
class PageSerializer(serializers.ModelSerializer):
id = serializers.CharField(source='slug')
class Meta:
model = Page
fields = ('name','id')
我在 http://localhost:8000/api/pages 得到的 JSON 响应如下
[
"name": "Page 1",
"id": "page-1"
,
"name": "Page 2",
"id": "page-2"
,
etc
]
当我使用 json API 时,做的完全一样,但显然是导入
from rest_framework_json_api import serializers
我无法以同样的方式更改 id 值,查看 http://localhost:8000/api/pages 时出现这样的情况
"links":
omitted for brevity ...
,
"data": [
"type": "pages",
"id": "1",
"attributes":
"name": "Page 1"
,
"type": "pages",
"id": "2",
"attributes":
"name": "Page 2"
,
]
【问题讨论】:
不要在fields
中包含'id'
。
你的模型中是否有现场蛞蝓?
如果你的模型有一个slug
字段,为什么不把它作为字段传递(并给它一个标签“id”)?
嗨 - 感谢您回来。如果我删除字段中的 'id' 则没有区别,抱歉,是的,我的模型中确实有 slug .. 为简洁起见,我没有在字段列表中显示它
@dirkgroten 抱歉,你能澄清一下吗?
【参考方案1】:
这是一种解决方案,它允许我查看例如 http://localhost:8000/api/pages 的响应,并以 Emberjs(期望响应符合 JSON API 规范)不会抱怨的格式向 http://localhost:8000/api/pages/some-slug 发出请求。
在我的序列化器(PageSerializer.py)中:
from rest_framework_json_api import serializers
from .models import Page
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
fields = ('name','id','url','slug')
lookup_field = 'slug'
// if you want to show the links field in the response
extra_kwargs = 'url': 'lookup_field':'slug'
在视图中(PageViewSet)
from rest_framework import viewsets
from .models import Page
from .serializers import PageSerializer
class PageViewSet(viewsets.ModelViewSet):
queryset = Page.objects.all().order_by('name')
serializer_class = PageSerializer
lookup_field = 'slug'
路由器保持不变:
from django.urls import path, include
from rest_framework import routers
from page import views
router = routers.DefaultRouter(trailing_slash=False)
router.register('pages',views.PageViewSet)
urlpatterns = [
path('api/',include(router.urls)),
]
【讨论】:
【参考方案2】:我认为您想要的是使用您的 slug 字段而不是 id 作为您的主键,以便您可以在您的 url 中传递该参数以获得所需的结果。 您可以在您的网址中执行类似的操作
url(r'^something-here/(?P<slug>[\w-]+)/$', "your_view_name_here", name='name_you_want')
在您的观点中,您可以执行以下操作:
class YourListAPIView(ListAPIView):
serializer_class = YourSerializer
def get_queryset(self):
slug = self.kwargs['slug']
return ModelName.objects.filter(slug=slug)
【讨论】:
很抱歉没有更清楚地解释这一点 - 我希望通过在我最初的问题中给出标准 REST 框架中的示例,有一种简单的方法可以使用 json api 实现相同的目标。在 json 响应中(显示在原始问题中),“id”字段需要显示 slug。我不认为这可以实现,但如果我弄错了,请道歉 我认为你的想法是错误的。您的最终结果是使用 id 作为 url 中的参数,以便您可以在 url 中传递 slug 并获得响应。对吗? 嗨。是的,我希望能够使用 slug 来获取实例响应,例如 localhost:8000/api/pages/some-page 与 localhost:8000/api/pages/1 但在查看 localhost:8000/api/pages 的所有页面的响应时,该响应需要包含 id 的 slug 值,不是整数 - 请参阅上面的修正问题。我可以使用“标准”DRF(参见修改后的问题)来实现这一点,但当我使用我想要的 rest_framework_json_api 时却没有得到相同的结果。 @Newfoundland id 是默认字段和默认主键。正如你所说,你的模型领域已经有了 slug。使用该字段作为您的 url 参数。如上所述在我的回答中更改您的 url,以便在您要调用 API url 时它接受 slug。之后,只需使用 slug 并在您的视图中做一些事情。 很抱歉,这无法正常工作。如果我在我的视图中使用 generics.ListAPIView,利用从 rest_framework_json_api 使用 serializers.ModelSerializer 的 PageSerializer 类,我会收到此错误 AssertionError:basename
参数未指定,并且无法从视图集中自动确定名称,因为它没有.queryset
属性。别担心,我只需将 Django 模型中的主键更改为 slug。以上是关于在带有 json api 的 django rest 框架中使用 slug 而不是 ID的主要内容,如果未能解决你的问题,请参考以下文章
在带有 json api 的 django rest 框架中使用 slug 而不是 ID
在 Django 中为来自客户端的请求和来自服务器的响应(REST API)压缩 JSON 有效负载。