我有一个相当简单的检索测试:
def test_user_retrieve(self):
factory = APIRequestFactory()
User.objects.create_superuser(username='test', password='Welcome2', email='[email protected]')
user = User.objects.get(username='test')
view = UserViewSet.as_view({'get': 'retrieve'})
url = reverse('core:user-detail')
request = factory.get(url)
force_authenticate(request, user=user)
response = view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
它给出了以下回溯:
Traceback (most recent call last):
File "D:\Projects\enterpass\api\core\tests.py", line 54, in test_user_retrieve
url = reverse('core:user-detail')
File "D:\Python36\lib\site-packages\django\urls\base.py", line 88, in reverse
return iri_to_uri(resolver._reverse_with_prefix(view, prefix, *args, **kwargs))
File "D:\Python36\lib\site-packages\django\urls\resolvers.py", line 632, in _reverse_with_prefix
raise NoReverseMatch(msg)
django.urls.exceptions.NoReverseMatch: Reverse for 'user-detail' with no arguments not found. 2 pattern(s) tried: ['api/v1/core/users/(?P<pk>[^/.]+)\\.(?P<format>[a-z0-9]+)/?$', 'api/v1/core/users/(?P<pk>[^/.]+)/$']
如果我使用邮递员点击URL,则没有问题:
http://localhost:8000/api/v1/core/users/1/
该视图正在通过路由器进行注册,如下所示:
app_name = 'core'
router.register(r'users', views.UserViewSet, base_name='user')
这是相关视图的一部分:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes_by_action = {'list': [CanListUser],
'create': [CanCreateUser],
'retrieve': [CanRetrieveUser],
'update': [CanUpdateUser],
'destroy': [CanDestroyUser]}
def retrieve(self, request, pk=None, **kwargs):
try:
instance = self.get_object()
self.check_object_permissions(self.request, instance)
serializer = UserSerializer(instance, context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
except User.DoesNotExist:
return Response(status=status.HTTP_204_NO_CONTENT)
找到解决方案,但我希望有人根据这个工作视图为我解释:
def test_user_retrieve(self):
factory = APIRequestFactory()
User.objects.create_superuser(username='test', password='Welcome2', email='[email protected]')
user = User.objects.get(username='test')
view = UserViewSet.as_view({'get': 'retrieve'})
url = reverse('core:user-detail', args=(User.pk,))
request = factory.get(url)
force_authenticate(request, user=user)
response = view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
出于某种原因,我必须在URL中指定位置参数,然后在响应中我需要指定id。解决方案从这里拉出来:
我想你忘了用reverse
传递必需的参数。用下面的反向添加用户的pk。
userPK = 123 // User ID
url = reverse('core:user-detail', args=[userPK])