我正在使用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()应该为我做这件事,但我也尝试对@符号进行网址编码,如下所示:
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()系统找不到网址匹配?
编辑:
我在DRF的路由器上正常使用ViewSet,因此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')
答案 0 :(得分:2)
问题不是@
,而是.
。这是因为DRF路由器用于参数的默认正则表达式为[^/.]+
,具体排除了点。
您应该可以通过在视图集上设置lookup_value_regex
来覆盖它:
class UserViewSet(ModelViewSet):
lookup_field = 'email'
lookup_value_regex = r'[^/]+'