1

在我的 Django 项目中,我创建了自定义管理页面(不是来自 Django 的管理员)。我有 2 个登录页面。一个用于管理员,第二个用于其他用户。

在下面,您可以看到管理员的urls.py文件。我测试了它,它工作正常。成功登录后,Django 将用户重定向到下一个参数 ( /administration/dashboard/) 的 url。

我写了单元测试,它引发了错误。从错误中我了解到 Django 重定向到默认 url ( /accounts/profile/)。为什么单元测试不使用我在 urls.py 文件中所做的设置(下一个参数)?

如何解决这个问题?

现在我注意到只有LOGIN_REDIRECT_URL = '/administration/dashboard/'settings.py中使用此代码时问题才会消失。我不能使用它,因为将来我将用于LOGIN_REDIRECT_URL我的其他登录页面。

如果有任何帮助,我将不胜感激!

网址.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'),
]

测试.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)

表格.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
            }
        )

登录.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>
4

2 回答 2

0

Django 不是签nextextra_context而是签入GETPOST参数。

extra_context用于更新您的模板上下文。因此,如果您想将变量的值传递给您的模板,您可以使用extra_context.

但是,您可以通过设置LOGIN_REDIRECT_URLsettings.py或传递 next 作为 POST 或 GET 参数来修复您的测试。

params = dict(**self.credentials, next=reverse("home:index"))
response = self.client.post(
    url,
    params,
    follow=True
)

笔记:

self.credentials应该在应用到的 dict 中解包self.data

self.data = dict(
    **self.credentials,
    next=reverse("administration:dashboard")
)

如果您想在不进行此更改的情况下进行测试,我可以推荐另一种测试方法。

您需要在浏览器中呈现您的模板并填写登录表单。这样,您的浏览器客户端将使用作为参数传递的POST请求。next您可以使用无头浏览器完成此操作selenium webdriver

于 2017-09-14T08:05:26.523 回答
0

您是否尝试过删除follow=TruePOST 请求中的 。您正在检查重定向,但您告诉requests模块遵循重定向,因此您的响应将直接是页面而不是302重定向 HTTP 响应。

更明确地说。您正在发送一个带有 的请求requests.post(follow=True),该请求将跟随302重定向到目标页面,您response将成为带有目标页面的 HTTP 200。即使目标页面是您想要的页面,测试断言也会失败,因为正在您的响应中寻找 HTTP 302 代码并且您已经遵循了重定向。

于 2017-09-14T12:55:29.767 回答