为什么我的测试功能没有激活用户?
Why is my test function not activating the user?
我有一个 django 电子邮件验证应用程序,它发送带有激活 url 的电子邮件,其中包含编码的用户 pk 和一个令牌,然后当应用程序在 url 中收到正确的数据时,它设置 user.is_active
布尔值到 True
。我写了一个测试,应该创建一个用户并发送一个带有它的编码 pk 和令牌的获取请求,但它无法激活我的用户,即使 url 是正确的(因为你将能够见下文)
views.py 包含注册功能和验证 class 基于视图。
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# ... process form data
user.save()
# Verification
email_subject = 'Activate your followerr account'
domain = get_current_site(request).domain
user_id = urlsafe_base64_encode(force_bytes(user.pk))
link = reverse('activate', kwargs={
'user_id': user_id,
'token': token_generator.make_token(user),
})
activate_url = 'http://' + domain + link
email_body = 'Hello ' + user.name + \
' please use this link to verify your account\n' + activate_url
email = EmailMessage(
email_subject,
email_body,
'noreply@domain.com',
[user.email],
)
email.send()
return redirect('login')
else:
form = SignupForm()
return render(request, 'signup.html', {'form': form})
class VerificationView(View):
def get(self, request, user_id, token):
try:
id = urlsafe_base64_decode(force_text(user_id))
user = User.objects.get(pk=id)
if not token_generator.check_token(user, token):
return HttpResponse('login failed')
if user.is_active:
return redirect('login')
user.is_active = True
user.save()
return redirect('login')
except Exception as ex:
pass
return redirect('login')
在我的测试中,我用 post 请求创建了一个新用户,并检查电子邮件是否存在,然后我从发件箱中唯一的电子邮件中获取令牌(这不是最好的方法我'我确定,但它现在可以工作),获取 user_id 并将其编码为 url,然后向视图发送一个获取请求,该视图应该可以找到具有 user_id 的用户,查看是否有令牌匹配用户并将 user.is_active
设置为 True
并重定向到 login
页面,但是在所有这些完成后我的 user.is_active
值仍然保持 False
。这是测试:
tests.py
def test_signup_email_confirmation(self):
response = self.client.post('/signup/', data={'email': 'test1@gmail.com',
'name': 'test1',
'gender': True,
'password1': 'test1',
'password2': 'test1'}, follow=True)
self.assertEqual(len(mail.outbox), 1)
for i in mail.outbox:
token = i.body.split(' ')[-1]
print(i.body) # <-- the entire email body with the activation url
token = token[38:-1]
user = User.objects.get(email='test1@gmail.com')
user_id = urlsafe_base64_encode(force_bytes(user.pk))
activation_url = reverse('activate', kwargs={'user_id': user_id, 'token': token})
activation_url = 'http://testserver' + activation_url
res = self.client.get(activation_url, follow=True)
print(activation_url)
print(token_generator.check_token(user, token))
print(res.status_code)
print(user.is_active)
self.assertEqual(res.status_code, 200)
self.assertRedirects(response, '/login/')
我已经尝试过不使用 'http://testserver'
部分而使用 activation_url
。
打印语句的结果在这里:
Hello test1 please use this link to verify your account
http://testserver/activate/Mg/ad1ap1-887a3ff4466d2e1d098603ddad24355e/
http://testserver/activate/Mg/ad1ap1-887a3ff4466d2e1d098603ddad24355e/
200
True
False
如您所见 url 的匹配项,但 is_active
的值仍然是 False
。
发生这种情况的原因是因为 user
测试 class 中的对象是在 is_active
为 False
时从数据库加载的。当视图设置 is_active=True
并保存用户时,测试方法无法知道实例已修改。
因此,现在测试方法中的 user
实例仍然具有旧值。
如果要测试修改后的字段,保存后必须让Django刷新对象:
user.refresh_from_db()
print(user.is_active)
我有一个 django 电子邮件验证应用程序,它发送带有激活 url 的电子邮件,其中包含编码的用户 pk 和一个令牌,然后当应用程序在 url 中收到正确的数据时,它设置 user.is_active
布尔值到 True
。我写了一个测试,应该创建一个用户并发送一个带有它的编码 pk 和令牌的获取请求,但它无法激活我的用户,即使 url 是正确的(因为你将能够见下文)
views.py 包含注册功能和验证 class 基于视图。
def signup(request):
if request.method == 'POST':
form = SignupForm(request.POST)
if form.is_valid():
# ... process form data
user.save()
# Verification
email_subject = 'Activate your followerr account'
domain = get_current_site(request).domain
user_id = urlsafe_base64_encode(force_bytes(user.pk))
link = reverse('activate', kwargs={
'user_id': user_id,
'token': token_generator.make_token(user),
})
activate_url = 'http://' + domain + link
email_body = 'Hello ' + user.name + \
' please use this link to verify your account\n' + activate_url
email = EmailMessage(
email_subject,
email_body,
'noreply@domain.com',
[user.email],
)
email.send()
return redirect('login')
else:
form = SignupForm()
return render(request, 'signup.html', {'form': form})
class VerificationView(View):
def get(self, request, user_id, token):
try:
id = urlsafe_base64_decode(force_text(user_id))
user = User.objects.get(pk=id)
if not token_generator.check_token(user, token):
return HttpResponse('login failed')
if user.is_active:
return redirect('login')
user.is_active = True
user.save()
return redirect('login')
except Exception as ex:
pass
return redirect('login')
在我的测试中,我用 post 请求创建了一个新用户,并检查电子邮件是否存在,然后我从发件箱中唯一的电子邮件中获取令牌(这不是最好的方法我'我确定,但它现在可以工作),获取 user_id 并将其编码为 url,然后向视图发送一个获取请求,该视图应该可以找到具有 user_id 的用户,查看是否有令牌匹配用户并将 user.is_active
设置为 True
并重定向到 login
页面,但是在所有这些完成后我的 user.is_active
值仍然保持 False
。这是测试:
tests.py
def test_signup_email_confirmation(self):
response = self.client.post('/signup/', data={'email': 'test1@gmail.com',
'name': 'test1',
'gender': True,
'password1': 'test1',
'password2': 'test1'}, follow=True)
self.assertEqual(len(mail.outbox), 1)
for i in mail.outbox:
token = i.body.split(' ')[-1]
print(i.body) # <-- the entire email body with the activation url
token = token[38:-1]
user = User.objects.get(email='test1@gmail.com')
user_id = urlsafe_base64_encode(force_bytes(user.pk))
activation_url = reverse('activate', kwargs={'user_id': user_id, 'token': token})
activation_url = 'http://testserver' + activation_url
res = self.client.get(activation_url, follow=True)
print(activation_url)
print(token_generator.check_token(user, token))
print(res.status_code)
print(user.is_active)
self.assertEqual(res.status_code, 200)
self.assertRedirects(response, '/login/')
我已经尝试过不使用 'http://testserver'
部分而使用 activation_url
。
打印语句的结果在这里:
Hello test1 please use this link to verify your account
http://testserver/activate/Mg/ad1ap1-887a3ff4466d2e1d098603ddad24355e/
http://testserver/activate/Mg/ad1ap1-887a3ff4466d2e1d098603ddad24355e/
200
True
False
如您所见 url 的匹配项,但 is_active
的值仍然是 False
。
发生这种情况的原因是因为 user
测试 class 中的对象是在 is_active
为 False
时从数据库加载的。当视图设置 is_active=True
并保存用户时,测试方法无法知道实例已修改。
因此,现在测试方法中的 user
实例仍然具有旧值。
如果要测试修改后的字段,保存后必须让Django刷新对象:
user.refresh_from_db()
print(user.is_active)