Python 如何在Django框架中使用自定义权限对POST请求进行单元测试?

Python 如何在Django框架中使用自定义权限对POST请求进行单元测试?,python,django,unit-testing,django-rest-framework,Python,Django,Unit Testing,Django Rest Framework,各位。我希望你做得很好。我是Django新手,试图学习RESTful开发的基础知识。我只懂Python,所以Django REST框架目前最适合我 现在我正在尝试为我的API实现单元测试。这是一个简单的模型,可以在NBA球员的名字和身高上实现CRUD。在我的模型中,我添加了一个类来描述这些数据,并将其转换为具有ModelViewSet的视图。我想让这些数据只对特定类型的用户(读写用户)可编辑,只对另一个用户(只读用户)可读,并且对未经身份验证的用户不可接受。为此,我创建了一个自定义用户模型,并使

各位。我希望你做得很好。我是Django新手,试图学习RESTful开发的基础知识。我只懂Python,所以Django REST框架目前最适合我

现在我正在尝试为我的API实现单元测试。这是一个简单的模型,可以在NBA球员的名字和身高上实现CRUD。在我的模型中,我添加了一个类来描述这些数据,并将其转换为具有ModelViewSet的视图。我想让这些数据只对特定类型的用户(读写用户)可编辑,只对另一个用户(只读用户)可读,并且对未经身份验证的用户不可接受。为此,我创建了一个自定义用户模型,并使用自定义权限将其转换为我的视图。现在我想写几个单元测试来检查:

  • r/w用户可以创建一个新的播放器
  • r/w用户可以获得玩家列表
  • r/o用户无法创建新播放器
  • r/o用户可以获得玩家列表
  • 未经验证的用户无法创建新播放器
  • 未经身份验证的用户无法获取玩家列表
  • 到目前为止,我已经在GET请求上运行了单元测试,输出为OK。但是我在请求后测试中遇到了问题,得到了401的响应状态代码(我应该得到201代码)。这段代码意味着我的用户没有授权这样做,但我无法在测试中指出发生这种情况的原因。在运行我的服务器时,我添加到我的用户中的角色额外字段起作用,在从命令行创建用户时也起作用

    这是我的
    型号.py

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class User(AbstractUser):
        ROLES = [('read-only', 'read-only'), ('read-write', 'read-write'),]
        role = models.CharField(max_length=32, choices=ROLES, default='read-only')
    # Create your models here.
    class NBAplayers(models.Model):
        first_name = models.CharField(max_length=100)
        h_in = models.DecimalField(max_digits=5, decimal_places=2)
        h_meters = models.DecimalField(max_digits=5, decimal_places=2)
        last_name = models.CharField(max_length=120)
    
        def __str__(self):
            return self.first_name
    
    class TestUserBase(TestCase):
    
        username = 'randomuser'
        password = 'randompassword'
    
        def setUp(self):
            super().setUp()
    
            User = get_user_model()
    
            self.user = User.objects.create_user(username='randomuser',
                                                 password='randompassword')
            self.user.role = self.user_type
            self.user.save()
    
    class ReadWriteUserTest(TestUserBase):
    
        url = urls.reverse('Players list-list')
        user_type = 'read-write'
    
        def setUp(self):
            super().setUp()
    
    
            # self.assertTrue(self.client.login(username=self.username,
                                              #password=self.password))
    
        def test_read_write_user_GET_REQUEST(self):
            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
    
        def test_read_write_user_POST_REQUEST(self):
            response = self.client.post(self.url, {
                'id':'4'
                'first_name':'John',
                'h_in' : '77',
                'h_meters' : '1.96',
                'last_name' : 'Doe',
                })
            self.assertEqual(response.status_code, 201)
    
    和my
    views.py
    ,其中我添加了自定义权限:

    class ReadOnlyPermission(permissions.BasePermission):
    
      def has_permission(self, request, view):
        requests = ('POST', 'PUT', 'DELETE', 'PATCH')
        user = request.user
        if user.is_anonymous:  # Not Authenticated
            return request.method == 'GET'            
        else:    
            if user.role == 'read-write':
                return request.method in requests + ('GET',)
            else:  # Read Only User
                return request.method == 'GET'
    
    class NBAPlayersViewSet(viewsets.ModelViewSet):
        serializer_class = NBAplayersSerializer
        queryset = NBAplayers.objects.all()
        permission_classes = [ReadOnlyPermission]
    
    最后,我的
    tests.py

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    
    class User(AbstractUser):
        ROLES = [('read-only', 'read-only'), ('read-write', 'read-write'),]
        role = models.CharField(max_length=32, choices=ROLES, default='read-only')
    # Create your models here.
    class NBAplayers(models.Model):
        first_name = models.CharField(max_length=100)
        h_in = models.DecimalField(max_digits=5, decimal_places=2)
        h_meters = models.DecimalField(max_digits=5, decimal_places=2)
        last_name = models.CharField(max_length=120)
    
        def __str__(self):
            return self.first_name
    
    class TestUserBase(TestCase):
    
        username = 'randomuser'
        password = 'randompassword'
    
        def setUp(self):
            super().setUp()
    
            User = get_user_model()
    
            self.user = User.objects.create_user(username='randomuser',
                                                 password='randompassword')
            self.user.role = self.user_type
            self.user.save()
    
    class ReadWriteUserTest(TestUserBase):
    
        url = urls.reverse('Players list-list')
        user_type = 'read-write'
    
        def setUp(self):
            super().setUp()
    
    
            # self.assertTrue(self.client.login(username=self.username,
                                              #password=self.password))
    
        def test_read_write_user_GET_REQUEST(self):
            response = self.client.get(self.url)
            self.assertEqual(response.status_code, 200)
    
        def test_read_write_user_POST_REQUEST(self):
            response = self.client.post(self.url, {
                'id':'4'
                'first_name':'John',
                'h_in' : '77',
                'h_meters' : '1.96',
                'last_name' : 'Doe',
                })
            self.assertEqual(response.status_code, 201)
    
    )

    使用
    AUTH\u user\u MODEL='api\u basic.user'
    将自定义用户添加到全局设置所需的上述所有代码。所以,我阅读了文档,四处搜索,试图理解如何编写这个特定的测试,我基本上遵循了每个人使用的一般结构。我在命令行上单独运行了代码,在运行
    response=self.client.post(self.url,{…
    之后,我得到了以下错误:

    django line 750, in post self.extra = extra AttributeError: 'str' object has no attribute 'extra'
    
    有谁能解释一下这意味着什么,以及如何使用它来修复我的测试?事先感谢您提供的任何帮助或意见。干杯