在我的Django项目中,我创建了自定义管理页面(不是来自Django的管理员)。我有2个登录页面。一个用于管理员,另一个用于其他用户。
下面您可以看到管理员的 urls.py 文件。我测试它,它工作正常。成功登录后,Django会将用户重定向到 next 参数(/administration/dashboard/
)的网址。
我写了单元测试,它引发了错误。从错误我明白Django重定向到默认网址(/accounts/profile/
)。为什么单元测试不使用我在urls.py文件中做的设置(下一个参数)?
如何解决这个问题?
现在我注意到只有在 settings.py 中使用此代码LOGIN_REDIRECT_URL = '/administration/dashboard/'
时问题才会消失。我无法使用它,因为将来我会将LOGIN_REDIRECT_URL
用于我的其他登录页面。
我将不胜感激任何帮助!
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:
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
)
错误:
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:
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:
<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>
答案 0 :(得分:0)
Django isn't checking next
in extra_context
但在GET
和POST
参数中。
extra_context
is used to update your template context。因此,如果您想将变量值传递给模板,可以使用extra_context
设置它们。
但是,您可以通过setting LOGIN_REDIRECT_URL
in settings.py
修复测试,或者将其作为POST或GET参数传递给下一个。
params = dict(**self.credentials, next=reverse("home:index"))
response = self.client.post(
url,
params,
follow=True
)
self.credentials
应该在应用于self.data
的字典中解压缩。
self.data = dict(
**self.credentials,
next=reverse("administration:dashboard")
)
如果您想在不进行此更改的情况下进行测试,我可以推荐另一种方法来测试它。
您需要在浏览器中呈现模板并填写登录表单。这样,您的浏览器客户端就会将POST
请求作为参数传递next
。
您可以使用selenium webdriver
无头浏览器完成此操作。
答案 1 :(得分:0)
您是否尝试删除POST请求中的follow=True
。您正在检查重定向,但是您告诉requests
模块遵循重定向,因此您的响应将直接是页面,而不是302
重定向HTTP响应。
更明确。您正在发送requests.post(follow=True)
的请求,该请求将遵循302
重定向到目标网页,而您的response
将是带有目标网页的HTTP 200。即使目标页面是您想要的页面,测试断言也会失败,因为您在响应中查找了HTTP 302代码并且您已经遵循了重定向。