【发布时间】:2019-11-07 09:56:23
【问题描述】:
随着我添加新视图和更多功能,我将继续测试我的 Django Rest Framework 应用程序。我必须承认,在这个阶段,我发现测试比实际编码和构建我的应用程序更难。我觉得测试 DRF 可用的资源比谈论使用 DRF 构建 REST 框架的资源少得多。不过,C'est la vie,我继续战斗。
我目前面临的问题是在测试我的一个 DRF 视图集时收到 403 错误。我可以确认视图及其权限在使用浏览器或常规 python 脚本访问端点时工作正常。
让我们从我的 ViewSet 中使用的模型开始
class QuizTracking(models.Model):
case_attempt = models.ForeignKey(CaseAttempt, on_delete=models.CASCADE)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
answer = models.ForeignKey(Answer, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
这里需要注意的是,用户有一个 FK。这在确定权限时使用。
这是我的测试功能。为简洁起见,我没有包含整个类的代码。
def test_question_retrieve(self):
"""
Check that quiz tracking/ID returns a 200 OK and the content is correct
"""
jim = User(username='jimmy', password='monkey123', email='jimmy@jim.com')
jim.save()
quiz_tracking = QuizTracking(answer=self.answer, case_attempt=self.case_attempt, user=jim)
quiz_tracking.save()
request = self.factory.get(f'/api/v1/progress/quiz-tracking/{quiz_tracking.id}')
# How do I refernce my custom permission using Permission.objects.get() ?
# permission = Permission.objects.get()
# jim.user_permissions.add(permission)
self.test_user.refresh_from_db()
force_authenticate(request, user=jim)
response = self.quiz_detail_view(request, pk=quiz_tracking.id)
print(response.data)
print(jim.id)
print(quiz_tracking.user.id)
self.assertContains(response, 'answer')
self.assertEqual(response.status_code, status.HTTP_200_OK)
在上面的代码中,我定义了一个用户jim 和一个quiz_tracking 拥有的jim 对象。
我构建我的请求,force_authenticate 请求并执行我的请求并将响应存储在 response。
这里需要注意的有趣的事情是: - jim.id 和 quiz_tracking.user.id 是相同的值 - 我收到 403 响应,带有
{'detail': ErrorDetail(string='You do not have permission to perform this action.', code='permission_denied')}
你可能已经注意到我已经注释掉了permission = Permission.objects.get() 我的理解是我需要通过这个我的权限类,在我的例子中是IsUser。但是,我的数据库中没有这方面的记录,因此 Permission.objects.get('IsUSer') 调用失败。
所以我的问题如下: - 如何验证我的请求以便收到 200 OK? - 我是否需要在我的测试中为我的用户添加权限,如果需要,需要哪些权限以及使用什么语法?
下面是我的视图,下面是我定义IsUser的自定义权限文件
class QuickTrackingViewSet(viewsets.ModelViewSet):
serializer_class = QuizTrackingSerializser
def get_queryset(self):
return QuizTracking.objects.all().filter(user=self.request.user)
def get_permissions(self):
if self.action == 'list':
self.permission_classes = [IsUser, ]
elif self.action == 'retrieve':
self.permission_classes = [IsUser, ]
return super(self.__class__, self).get_permissions()
注意如果我注释掉def get_permissions(),那么我的测试就可以通过了。
我的自定义permission.py
from rest_framework.permissions import BasePermission
class IsSuperUser(BasePermission):
def has_permission(self, request, view):
return request.user and request.user.is_superuser
class IsUser(BasePermission):
def has_object_permission(self, request, view, obj):
if request.user:
if request.user.is_superuser:
return True
else:
return obj == request.user
else:
return False
干杯,
C
【问题讨论】:
标签: django python-3.x django-rest-framework