首页 > 解决方案 > 使用 DRF 测试自定义用户的创建

问题描述

目标是测试使用APITestCase创建新的自定义用户。

在 models.py 中有两个新类分别继承自AbstractBaseUserBaseUserManager

class MyUser(AbstractBaseUser):
    objects = MyUserManager()
    class Meta:
        db_table = 'user_entity'

    user_id = models.AutoField(primary_key=True)
    #username = models.CharField(max_length=USERNAME_MAX_LENGTH, unique=True, validators=[validators.validate_username])
    username = models.CharField(max_length=20, unique=True)
    password = models.CharField(max_length=256)
    first_name = models.CharField(max_length=25)
    last_name = models.CharField(max_length=25)
    email = models.EmailField(verbose_name='email', max_length=100, unique=True)
    last_access = models.DateField(default=datetime.date.today)
    creation_date = models.DateTimeField(default=timezone.now)
    last_update = models.DateField(default=datetime.date.today)
    user_type = models.IntegerField()
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = ['username', 'first_name', 'last_name', 'user_type']

    def __str__(self):
        return str(self.user_id) + " (%s)" % str(self.email)

    def has_perm(self, perm, obj=None):
        return self.user_type == 0

    def has_module_perms(self, app_label):
        return True

class MyUserManager(BaseUserManager):
    def _create_generic_user(self, email, username, password, first_name, last_name, user_type):
        if not username:
            raise ValueError("Username cannot be empty")
        if not email:
            raise ValueError("Email cannot be empty")
        if not first_name:
            raise ValueError("First name cannot be empty")
        if not last_name:
            raise ValueError("Last name cannot be empty")
        if not password:
            raise ValueError("Password cannot be empty")

        user = self.model(
            username=username,
            first_name=first_name,
            last_name=last_name,
            email=self.normalize_email(email),
            user_type=user_type,
            is_staff=user_type == 0,
            is_active=False
        )
        user.set_password(password)
        user.save(user=self._db)
        return user

    def create_user(self, email, username, password, first_name, last_name):
        return self._create_generic_user(email, username, password, first_name, last_name, 2)

    def create_admin(self, email, username, password, first_name, last_name):
        return self._create_generic_user(email, username, password, first_name, last_name, 0)

然后,在 serializers.py 中为从 ModelSerializer 继承的 DRF 创建了一个MyUserSerializer

class MyUserSerializer(serializers.ModelSerializer):
    email = serializers.EmailField(
            required=True, # make sure email is provided
            validators=[UniqueValidator(queryset=MyUser.objects.all())] # make sure email is unique
            )
    username = serializers.CharField(
            required=True,
            validators=[UniqueValidator(queryset=MyUser.objects.all())],
            min_length=5,
            max_length=20
            )
    password = serializers.CharField(
            write_only=True,
            required=True,
            max_length=256
            )
    first_name = serializers.CharField(
            required=True,
            max_length=25
            )
    last_name = serializers.CharField(
            required=True,
            max_length=25
            )

    def create(self, validated_data):
        user = MyUser.objects.create_user(validated_data['email'], validated_data['username'], validated_data['password'],
        validated_data['first_name'], validated_data['last_name'])
        return user


    class Meta:
        model = MyUser
        fields = ('user_id', 'email', 'username', 'password', 'first_name', 'last_name')

带有 APIView 的视图

class MyUserCreate(APIView):
    """ 
    Creates the user. 
    """

    def post(self, request, format='json'):
        serializer = MyUserSerializer(data=request.data)
        if serializer.is_valid():
            user = serializer.save()
            if user:
                return Response(serializer.data, status=status.HTTP_201_CREATED)

和网址

urlpatterns = [
    url(r'api/users^$', views.MyUserCreate.as_view(), name='user-create'),
]

以此为基础,接着创建一个简单的创建用户测试

class MyUserTest(APITestCase):
    def setUp(self):
        # Create a user
        self.test_user = MyUser.objects.create_user('tiagomartinsperes@gmail.com', 'tiagoperes', 'EWFdfew45te!sadf32', 'Tiago', 'Peres')

        # URL for creating user
        self.create_url = reverse('user-create')

    def test_create_user(self):
        """
        Ensure we can create a new user and a valid token is created with it.
        """
        data = {
            'email': 'cnf32344@zzrgg.com',
            'username': 'andresantos',
            'password': 'test',
            'first_name': 'André',
            'last_name': 'Santos'
        }

        response = self.client.post(self.create_url , data, format='json')

        # Make sure we have two users in the database
        self.assertEqual(MyUser.objects.count(), 2)
        # Return 201
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        # Return the username and email upon successful creation
        self.assertEqual(response.data['email'], data['email'])
        self.assertEqual(response.data['username'], data['username'])
        self.assertFalse('password' in response.data)
        self.assertEqual(response.data['first_name'], data['first_name'])
        self.assertEqual(response.data['last_name'], data['last_name'])

事情是,跑步

python manage.py test

得到以下错误:

为别名“默认”创建测试数据库...系统检查未发现问题(0 静音)。E ================================================== ===================== 错误:test_create_user (user.tests.MyUserTest) 确保我们可以创建一个新用户并使用它创建一个有效的令牌。-------------------------------------------------- -------------------- Traceback(最近一次通话最后一次):文件“C:\Users\tiago\Desktop\letsgo\COVID19-be\django_server\user\tests .py",第 10 行,在设置中 self.test_user = MyUser.objects.create_user('tiagomartinsperes@gmail.com', 'tiagoperes', 'EWFdfew45te!sadf32', 'Tiago', 'Peres') 文件 "C:\ Users\tiago\Desktop\letsgo\COVID19-be\django_server\user\models.py”,第 38 行,在 create_user 中返回 self._create_generic_user(电子邮件,

-------------------------------------------------- -------------------- 在 0.172 秒内运行 1 次测试

FAILED (errors=1) 正在销毁别名“default”的测试数据库...

并且没有创建用户。我能做些什么来解决它?

标签: pythondjangoauthenticationtestingdjango-rest-framework

解决方案


问题在这里

user.save(user=self._db)

django 模型save具有以下签名。

def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):

由于您将数据库作为值(self._db)传递,我认为您应该编写

user.save(using=self._db)

推荐阅读