使用路由器为 ModelViewSet 的检索方法创建自定义或修改的 url
creating custom or modified url using router for retrive method of ModelViewSet
我想使用 ModelViewSet 的路由器创建自定义或修改的 url。
当前场景:
/models.py
class BlogPost(models.Model):
title = models.CharField(max_length=300)
description = models.TextField()
slug = models.SlugField(max_length=300, unique=True)
/serializers.py
class BlogListSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
exclude = ('id',)
/views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
/urls.py
router = DefaultRouter()
router.register(r'blog', BlogViewSet, basename='blog')
urlpatterns = router.urls
现在,我可以按如下方式访问 url:
检索https://localhost:8000/blog/1
如您所见,可以使用 pk 或 id 调用检索 url。
但是我创建了一个名为 slug 的模型字段,它是独一无二的。我的问题是如何修改 retrieve url 以便我可以使用 slug 字段调用 retrieve url 。例如:https://localhost:8000/blog/test-slug
注意:为什么我要使用 slug 创建 url?
答:我想使用 urls 作为站点地图。
# add a new url in your urlpatterns
urlpatterns = [
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
]
# In views.py define a class Blogdetail or make changes in the existing class
class Blogdetail(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_queryset(self):
slug = self.request.query_params.get("slug", None)
if slug == None:
queryset = self.queryset
else:
queryset = self.queryset.filter(slug = slug)
return queryset
如果您的 api 需要通过查询 slug 字段(而不是 pk
字段)得到 return 结果,您可以使用 lookup_field
和 lookup_url_kwarg
的 DRF.
pk
或 id
字段查找是默认查找并在 DRF 文档中提到。
https://www.django-rest-framework.org/api-guide/generic-views/
views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'slug'
class Blogdetail(generics.RetrieveAPIView):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_object(self):
slug = self.kwargs["slug"]
obj = get_object_or_404(BlogPost, slug=slug)
return obj
class BlogUrlHyperlinkedIdentityField(serializers.HyperlinkedIdentityField)
def get_url(self, obj, view_name, request, format):
kwargs = {
"slug": obj.slug
}
return reverse(view_name, kwargs=kwargs, request=request, format=format)
class BlogListSerializer(serializers.ModelSerializer):
url = BlogUrlHyperlinkedIdentityField("blog_detail")
class Meta:
model = BlogPost
fields = [
"url",.....]
同时添加 url
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
我想使用 ModelViewSet 的路由器创建自定义或修改的 url。
当前场景:
/models.py
class BlogPost(models.Model):
title = models.CharField(max_length=300)
description = models.TextField()
slug = models.SlugField(max_length=300, unique=True)
/serializers.py
class BlogListSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
exclude = ('id',)
/views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
/urls.py
router = DefaultRouter()
router.register(r'blog', BlogViewSet, basename='blog')
urlpatterns = router.urls
现在,我可以按如下方式访问 url:
检索https://localhost:8000/blog/1
如您所见,可以使用 pk 或 id 调用检索 url。 但是我创建了一个名为 slug 的模型字段,它是独一无二的。我的问题是如何修改 retrieve url 以便我可以使用 slug 字段调用 retrieve url 。例如:https://localhost:8000/blog/test-slug
注意:为什么我要使用 slug 创建 url? 答:我想使用 urls 作为站点地图。
# add a new url in your urlpatterns
urlpatterns = [
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
]
# In views.py define a class Blogdetail or make changes in the existing class
class Blogdetail(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_queryset(self):
slug = self.request.query_params.get("slug", None)
if slug == None:
queryset = self.queryset
else:
queryset = self.queryset.filter(slug = slug)
return queryset
如果您的 api 需要通过查询 slug 字段(而不是 pk
字段)得到 return 结果,您可以使用 lookup_field
和 lookup_url_kwarg
的 DRF.
pk
或 id
字段查找是默认查找并在 DRF 文档中提到。
https://www.django-rest-framework.org/api-guide/generic-views/
views.py
class BlogViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogListSerializer
lookup_field = 'slug'
lookup_url_kwarg = 'slug'
class Blogdetail(generics.RetrieveAPIView):
queryset = BlogPost.objects.all()
serializer_class = BlogDetailsSerializer
def get_object(self):
slug = self.kwargs["slug"]
obj = get_object_or_404(BlogPost, slug=slug)
return obj
class BlogUrlHyperlinkedIdentityField(serializers.HyperlinkedIdentityField)
def get_url(self, obj, view_name, request, format):
kwargs = {
"slug": obj.slug
}
return reverse(view_name, kwargs=kwargs, request=request, format=format)
class BlogListSerializer(serializers.ModelSerializer):
url = BlogUrlHyperlinkedIdentityField("blog_detail")
class Meta:
model = BlogPost
fields = [
"url",.....]
同时添加 url
path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),