【问题标题】:creating custom or modified url using router for retrive method of ModelViewSet使用路由器为 ModelViewSet 的检索方法创建自定义或修改的 url
【发布时间】:2020-03-12 20:08:03
【问题描述】:

我想使用路由器为 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

现在,我可以访问如下网址:

列出https://localhost:8000/blog

检索https://localhost:8000/blog/1

如您所见,可以使用 pk 或 id 调用检索 url。 但是我创建了一个名为 slug 的模型字段,它是独一无二的。我的问题是如何修改检索 url,以便我可以使用 slug 字段调用检索 url。例如:https://localhost:8000/blog/test-slug

注意:为什么我要使用 slug 创建一个 url? 答:我想使用站点地图的网址。

【问题讨论】:

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


    【解决方案1】:

    如果您的 api 需要通过查询 slug 字段(而不是 pk 字段)返回结果,您可以使用 DRF 的 lookup_fieldlookup_url_kwarg

    pkid 字段查找是默认查找并在 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'
    

    【讨论】:

    • 这正是我想要的。
    【解决方案2】:
    # 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
    

    【讨论】:

      【解决方案3】:
      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",.....]
      

      同时添加网址

      path('blog/<slug:slug>/', views.Blogdetail.as_view(), name='blog_detail'),
      

      【讨论】:

        猜你喜欢
        • 2021-11-26
        • 1970-01-01
        • 2021-08-10
        • 1970-01-01
        • 2012-11-22
        • 1970-01-01
        • 2018-04-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多