python - 使用 DRF 测试自定义用户的创建
问题描述
目标是测试使用APITestCase创建新的自定义用户。
在 models.py 中有两个新类分别继承自AbstractBaseUser和BaseUserManager
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”的测试数据库...
并且没有创建用户。我能做些什么来解决它?
解决方案
问题在这里
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)
推荐阅读
- java - Java 使用 multimap 作为参数
- java - 如何在 Spring MVC 中获取 HttpServletRequest?
- javascript - push 方法在 JavaScript 中不起作用
- java - 并行流与串行流上的减少与收集方法
- flutter - 如何在 Flutter 中缓存来自 GraphQL 的查询和变异?
- python - python中斐波那契数列中大于N的最小值
- python - 仅重复函数 3 次然后更改 Python
- javascript - 代码不执行一个函数,该函数告诉找到一个可以被 1 到 10 的所有数字整除的数字
- google-cloud-platform - 在构建数据管道时处理云数据融合中的传入空值
- docker - Docker 文件 - 常见的 dll 项目参考?