Почему в django reverse () не может быть указан параметр электронной почты? - PullRequest
3 голосов
/ 21 октября 2019

Я использую 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
...

Почему система reverse () django не может найти соответствие URL?

РЕДАКТИРОВАТЬ: я использую ViewSets как обычно с маршрутизаторами DRF, поэтому 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')

1 Ответ

1 голос
/ 22 октября 2019

Проблема не в @, а в .. Это потому, что по умолчанию регулярное выражение, используемое маршрутизатором DRF для параметров, равно [^/.]+, что, в частности, исключает точки.

Вы можете изменить это, установив lookup_value_regex в наборе:

class UserViewSet(ModelViewSet):
    lookup_field = 'email'
    lookup_value_regex = r'[^/]+'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...