django rest框架动态url路由

Posted

技术标签:

【中文标题】django rest框架动态url路由【英文标题】:django rest framework dynamic url route 【发布时间】:2020-01-27 08:20:25 【问题描述】:

我目前正在 Django (2.2.5) 和 djangorestframework (3.10.3) 中做一个小项目。我在将视图连接到路由器时遇到问题。我真的很感激能有第二双眼睛帮助我找出问题所在

对于网址我尝试了以下两种:

router = routers.DefaultRouter()
router.register(r'<chatroom>', views.ChatRoomViewSet)
router.register(r'<str:chatroom>', views.ChatRoomViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path('api-auth/', include('rest_framework.urls',namespace='rest_framework')),
    path('admin/', admin.site.urls),
]

然后将路由器添加到 urlpatterns。

视图集是:

class ChatRoomViewSet(viewsets.ModelViewSet):

    queryset = ChatRoom.objects.all().order_by('name')
    serializer_class = ChatRoomSerializer
    lookup_field = 'name'

    def get_viewset(self, request, name=None):
        name = self.kwargs.get('name', None)
        queryset = ChatRoom.objects.filter(name=name)
        return queryset

序列化器是

class ChatRoomSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = ChatRoom
        fields = ['url', 'name']
        lookup_field = 'name'

型号是:

class ChatRoom(models.Model):
    name = models.CharField(max_length=255, default="")

    def __str__(self):
        return self.name

有什么我明显错过的吗?

【问题讨论】:

你目前的结果是什么?你的期望是什么? 我当前运行 curl 的结果是 curl -H 'Accept: application/json; indent=4' -u user:password 127.0.0.1:8000/first-room Not Found: /first-room [27/Sep/2019 04:21:40] "GET /first-room HTTP/1.1" 404 5038 我保存了几个房间,包括一个以 first-room 为名,我正在将那个房间的详细信息以 json 形式返回 我没有在您的问题上看到您的 urls.py 文件,只是查看路由器,这样可能没有足够的信息让我或其他人回答您的问题。这可能是因为您定义了路由器但未将其添加到您的 urlpattern 中,因此找不到 url 127.0.0.1:8000/first-room 如果您在第一个答案下看到我的 cmets,您将看到设置的 url 我更新了 urls 代码片段以包含 urlpatterns 【参考方案1】:

您需要在 urlpatterns 中添加路由器 url

urlpatterns = router.urls

如果已经声明了 url py 然后将该列表与 router.urls 列表连接

urlpatterns += router.urls

【讨论】:

我已经这样做了,正如我在第一个代码框 path('', include(router.urls)) 中提到的,它位于 urlpatterns = [] 数组中【参考方案2】:

有一点我想先提一下,让你看看:

似乎您注册了 1 个路径和 1 个视图两次(这不会引起您的问题,只是想提一下)

您将路径参数命名为 chatroom,但您改用 name

get_viewset 似乎不对,要覆盖默认查询集,您应该改用get_queryset 方法

如果你已经在参数列表中使用了参数名称,像 def get_viewset(self, request, name=None): 这样你就不必再使用 self.kwargs 来获取它,python 已经为你处理了,所以只需使用 @987654327 @函数内部

毕竟代码应该是这样的,

网址

router = routers.DefaultRouter()
router.register(r'(?P<chatroom>.*)', views.ChatRoomViewSet)

视图集

class ChatRoomViewSet(viewsets.ModelViewSet):

    queryset = ChatRoom.objects.all().order_by('name')
    serializer_class = ChatRoomSerializer
    lookup_field = 'pk' # This will use to get the specific ChatRoom, you can remove it also

    def get_queryset(self, chatroom=None):
        # if you want request, you could use request = self.request
        # chatroom is the name you named on your path (<chatroom>)
        queryset = ChatRoom.objects.filter(name=chatroom)
        return queryset

希望能帮助您解决问题!

【讨论】:

不幸的是,这并没有解决它 - 但谢谢!我忽略了我忘记添加 request 和 chatroom=none :) @ChakoraChandra,刚刚更新了答案。你可以看到我们注册的 url 不同,rest framework 使用正则表达式来匹配 url(它不像path)。所以试试吧.. 我只是得到错误 django.core.exceptions.ImproperlyConfigured: "^(?P.*)/(?P[^/.]+)/$" 是不是有效的正则表达式:将组名“name”重新定义为组 2;是第 1 组的第 18 位 那是另一回事。我不确定您要尝试做什么,但不要在路径上两次使用一个路径参数名称。 ^(?P&lt;chatroom&gt;.*)/(?P&lt;user_another_name&gt;[^/.]+)/$ 我没有使用您上面粘贴的确切行,django 2.2 改变了 django 处理 url 的方式【参考方案3】:

在您的视图集中将get_viewset 替换为get_queryset。此外,您可以在视图集中声明 queryset 属性或实现 get_queryset 函数。

【讨论】:

以上是关于django rest框架动态url路由的主要内容,如果未能解决你的问题,请参考以下文章

python-django rest framework框架之路由

django框架--路由系统

如何将命名空间 url 添加到 django-rest-framework 路由器视图集

在 Django Rest Framework 中测试时获取路由器 url 名称

二 Django框架,urls.py模块,views.py模块,路由映射与路由分发以及逻辑处理——url控制器

嵌套路由上的 Django REST 权限