[英]Unit test in Django dont see correct redirect url for successfull login?
In my Django project I create custom admin page (NOT admin from Django). 在我的Django项目中,我创建了自定义管理页面(不是Django的管理员)。 I have 2 login pages.
我有2个登录页面。 One for admin, second for other users.
一个用于管理员,第二个用于其他用户。
Here below you can see urls.py file for admin. 在下面,您可以看到admins的urls.py文件。 I test it and it works fine.
我对其进行了测试,并且效果很好。 After successful login Django redirect user to url which was next parameter (
/administration/dashboard/
). 成功登录后,Django将用户重定向到下一个参数url(
/administration/dashboard/
)。
I wrote unit test and it raise error. 我写了单元测试 ,它引发了错误。 From error I understand that Django redirect to default url (
/accounts/profile/
). 从错误中我了解到Django重定向到默认URL(
/accounts/profile/
)。 Why unit test dont use settings which I did in urls.py file (next parameter)? 为什么单元测试不使用我在urls.py文件(下一个参数)中所做的设置?
How to fix this problem? 如何解决这个问题?
Right now I notice that problem disappear only if I use this code LOGIN_REDIRECT_URL = '/administration/dashboard/'
in settings.py . 现在,我注意到只有在settings.py中使用此代码
LOGIN_REDIRECT_URL = '/administration/dashboard/'
,该问题才会消失。 I cant use it cause in the future I will use LOGIN_REDIRECT_URL
to my other login page. 我无法使用它,因为将来我将使用
LOGIN_REDIRECT_URL
进入其他登录页面。
I would be grateful for any help! 我将不胜感激!
urls.py: urls.py:
from django.contrib.auth import views as authentication_views
urlpatterns = [
# Administration Login
url(r'^login/$',
authentication_views.login,
{
'template_name': 'administration/login.html',
'authentication_form': AdministrationAuthenticationForm,
'extra_context': {
'next': reverse_lazy('administration:dashboard'),
},
'redirect_authenticated_user': True
},
name='administration_login'),
]
tests.py: tests.py:
class AdministrationViewTestCase(TestCase):
def setUp(self):
self.client = Client()
self.credentials = {'username': 'user', 'password': 'password'}
self.user = User.objects.create_user(self.credentials, is_staff=True)
self.data = dict(
self.credentials,
next=reverse("administration:dashboard")
)
def test_administration_authorization(self):
self.assertTrue(self.user)
# logged_in = self.client.login(**self.credentials)
# self.assertTrue(logged_in)
response = self.client.post(
reverse("administration:administration_login"),
self.data,
follow=True
)
# self.assertEqual(response.status_code, 302)
self.assertRedirects(
response,
reverse("administration:dashboard"),
status_code=302,
target_status_code=200
)
ERROR: 错误:
Traceback (most recent call last):
File "/home/nurzhan/CA/administration/tests.py", line 51, in test_administration_authorization
reverse("administration:dashboard"),
File "/srv/envs/py27/lib/python2.7/site-packages/django/test/testcases.py", line 271, in assertRedirects
% (response.status_code, status_code)
AssertionError: Response didn't redirect as expected: Response code was 200 (expected 302)
forms.py: forms.py:
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.utils.translation import ugettext_lazy as _
class AdministrationAuthenticationForm(AuthenticationForm):
"""
A custom authentication form used in the administration application.
"""
error_messages = {
'invalid_login': (
_("ERROR MESSAGE.")
),
}
required_css_class = 'required'
def confirm_login_allowed(self, user):
if not user.is_active or not user.is_staff:
raise forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={
'username': self.username_field.verbose_name
}
)
login.html: login.html:
<form action="{% url 'administration:administration_login' %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
<input type="hidden" name="next" value="{{ next }}"/>
</form>
Django isn't checking next
in extra_context
but in GET
and POST
params. Django不会在
extra_context
检查next
,而是在GET
和POST
参数中进行检查。
extra_context
is used to update your template context . extra_context
用于更新模板上下文 。 So if you want to pass the values for variables to your template you can set those with extra_context
. 因此,如果要将变量的值传递到模板,则可以使用
extra_context
进行设置。
However, you can fix your test by either setting LOGIN_REDIRECT_URL
in settings.py
or passing next as a POST or GET param. 但是,您可以通过在
settings.py
设置LOGIN_REDIRECT_URL
或将其作为POST或GET参数作为下一个参数来修复测试。
params = dict(**self.credentials, next=reverse("home:index"))
response = self.client.post(
url,
params,
follow=True
)
self.credentials
should be unpacked in the dict being applied toself.data
.self.credentials
应该在应用于self.data
的字典中解压缩。
self.data = dict(
**self.credentials,
next=reverse("administration:dashboard")
)
If you wanted to test without making this change, I can recommend another way to test this. 如果您想在不做任何更改的情况下进行测试,我可以建议另一种测试方法。
You need to render your template in a browser and fill out the login form. 您需要在浏览器中呈现模板并填写登录表单。 This way your browser client will make the
POST
request with next
passed as a parameter. 这样,您的浏览器客户端将发出
POST
请求,并将next
作为参数传递。 You can get this done with a headless browser using selenium webdriver
. 您可以使用
selenium webdriver
在无头浏览器中完成此操作。
Have you tried removing the follow=True
in the POST request. 您是否尝试过在POST请求中删除
follow=True
。 You are checking for a redirection but you are telling the requests
modules to follow the redirection, so your response will be directly the page and not the 302
redirection HTTP response. 您正在检查重定向,但是您告诉
requests
模块遵循重定向,因此您的响应将直接是页面,而不是302
重定向HTTP响应。
To be more explicit. 更明确地说。 You are sending a request with
requests.post(follow=True)
, that will follow the 302
redirection to the destination page and your response
will be a HTTP 200 with the destination page. 您正在发送带有
requests.post(follow=True)
的请求,该requests.post(follow=True)
将遵循302
重定向到目标页面,并且您的response
将是带有目标页面的HTTP 200。 Even if the destination page is the one you want, the test assertion will fail because is looking for a HTTP 302 code in your response and you've already followed the redirection. 即使目标页面是您想要的页面,测试断言也会失败,因为正在响应中寻找HTTP 302代码并且您已经遵循了重定向。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.