django的reverse()为什么不匹配电子邮件参数?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django的reverse()为什么不匹配电子邮件参数?相关的知识,希望对你有一定的参考价值。

我正在使用DRF ViewSet管理用户帐户:

class UserViewSet(ModelViewSet):
    lookup_field = 'email'
    queryset = User.objects.all()

并且有一个测试用例,如:

from django.urls import reverse
from .base import BaseApiTestCase


class UsersTestCase(BaseApiTestCase):

    def test_get_user_account(self):

        # ...Create a test user, login as test user...

        response = self.client.get(
            reverse('api:users-detail', kwargs={'email': 'test@user.com'}),
            content_type='application/json'
        )
        self.assertStatusCode(response, 200)

我收到错误:

django.urls.exceptions.NoReverseMatch: Reverse for 'users-detail' with keyword arguments '{'email': 'test@user.com'}' not found. 2 pattern(s) tried: ['api/users/(?P<email>[^/.]+)\.(?P<format>[a-z0-9]+)/?$', 'api/users/(?P<email>[^/.]+)/$']

据我了解,[^/.]+正则表达式应与test@user.com相匹配。

尽管reverse()应该为我做这件事,但我也尝试对@符号进行url编码,例如:

reverse('api:users-account', kwargs={'email': 'test%40user.com'}),

正在运行manage.py show_urls显示该URL可用:

...
/api/users/<email>/ api.views.users.UserViewSet api:users-detail
...

为什么django的reverse()系统找不到url匹配?

编辑:我通常在DRF的路由器上使用ViewSets,因此urls.py并不是超级相关,但是对于后代,这是相关部分:

from rest_framework import routers, permissions
from api import views
router = routers.DefaultRouter()
router.register(r'users', views.users.UserViewSet, base_name='users')
答案

问题不是@,是.。这是因为DRF路由器用于参数的默认正则表达式为[^/.]+,特别是不包括点。

您应该可以通过在视图集上设置lookup_value_regex来覆盖它:

class UserViewSet(ModelViewSet):
    lookup_field = 'email'
    lookup_value_regex = r'[^/]+'

以上是关于django的reverse()为什么不匹配电子邮件参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django.core.urlresolvers.reverse 中的 reverse()

Django知识点

我不知道何时在 django.core.urlresolvers 模块中使用 reverse()

当检索到的电子邮件与现有用户的电子邮件匹配时,django allauth facebook 重定向到注册?

Django REST EmailAddress 匹配查询不存在

Django 1.3 日志记录:未记录 500 个错误