为什么我正在测试的页面返回 301 响应而不是 200 响应?

问题描述 投票:0回答:3

我正在为我作为课程一部分编写的 django 项目中的基于类的视图编写测试。目前,我一直在尝试测试指向需要用户登录的编辑页面的视图。当然,正在编辑的项目也必须首先由该用户创建。

在测试本身中,我实例化了一个模型和一个用户,然后在尝试 get 编辑页面之前让用户登录。我希望响应的状态代码为 200,但它一直以 301 的形式返回。代码如下:

urls.py - 编辑页面的路径:

path('edit/<slug:slug>/', views.EditBulletin.as_view(), name='edit'),

models.py - 正在实例化的模型

class Bulletin(models.Model):
    title = models.CharField(max_length=40, unique=True)
    slug = models.SlugField(max_length=40, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE, 
                               related_name='bulletins')
    content = models.TextField()
    link = models.URLField()
    created_on = models.DateTimeField(auto_now_add=True)
    status = models.IntegerField(choices=STATUS, default=0)
    likes = models.ManyToManyField(User, related_name='bulletin_likes')
    edited = models.BooleanField(default=False)
    updated_on = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

    def number_of_likes(self):
        return self.likes.count()

views.py - 编辑页面视图中的 get 方法:

class EditBulletin(View):
    def get(self, request, slug, *args, **kwargs):
        queryset = Bulletin.objects.filter(status=1)
        bulletin = get_object_or_404(queryset, slug=slug, author=request.user)

        bulletin_form = BulletinForm(instance=bulletin)

        return render(
            request,
            'edit_bulletin.html',
            {
                'bulletin_form': bulletin_form,
                'bulletin': bulletin,
                'original_url_query': request.GET.get('query'),
            },
        )

test_views.py - setUpClass 方法和编辑页面测试(都在 TestViews(TestCase) 类中):

@classmethod
def setUpClass(cls):
    cls.user_1 = User.objects.create_user(username='test_user',
                                          password='test')

def test_get_edit_bulletin_page(self):
    bulletin_title = 'New Bulletin'
    title_slug = slugify(bulletin_title)

    self.client.login(username=self.user_1.username,
                      password=self.user_1.password)

    bulletin = Bulletin.objects.create(title=bulletin_title,
                                       slug=title_slug,
                                       author=self.user_1,
                                       content='This is a test bulletin.',
                                       link='https://www.google.ie/',
                                       edited=False)

    response = self.client.get(f'/edit/{bulletin.slug}')

    self.assertEqual(response.status_code, 200)
    self.assertTemplateUsed(response, 'edit_bulletin.html')

我试过使用self.client.force_login,但没有用,但我不确定我是否使用正确。

我还尝试在 Bulletin 对象实例化期间初始化多对多“喜欢”字段,但没有成功,因为我知道在管理面板中,如果不提供“喜欢”的值,我就无法批准公告,即喜欢它的用户。不过,我不确定我是否做对了。

我很困惑为什么要退回 301。我知道如果您输入与您未创建的公告相对应的编辑 URL,它会显示 404 页面。或者,至少,将 DEBUG 设置为 True,它会显示一个错误页面。

最后,以防万一它还不是很明显,我应该补充一下我是新手。所以如果上面有什么真的很愚蠢的事情向你跳来跳去,请保持温柔!

django django-models django-views django-testing django-users
3个回答
0
投票

301 可能是因为您用来请求编辑页面的 URL 与您定义的 URL 模式不完全匹配。

正是因为这些潜在的错误,您使用字符串插值构建 URL 的方法并不是最好的主意。尝试使用 Django 的

urls.reverse

    # test function start
    bulletin = Bulletin.objects.create(title=bulletin_title,
                                       slug=title_slug,
                                       author=self.user_1,
                                       content='This is a test bulletin.',
                                       link='https://www.google.ie/',
                                       edited=False)
    url = reverse('edit', kwargs={'slug': bulletin.slug})
    # test function assertions etc

这应该 always 构建与您在

urls.py
文件中定义的相同的 URL,因为在幕后,此方法实际上获得了您声明的相同路径。


0
投票

创建用户时,您将通过文本字符串设置密码。但是,此密码在存储在

user.password

之前会经过哈希处理

然后当您尝试使用存储的散列密码

user.password
登录时,提供的密码在比较之前再次散列。这将失败并可能导致重定向。

试试

self.client.login(username=self.user_1.username,
                      password="test")

0
投票
urls.py
path('edit/<slug:slug>/', views.EditBulletin.as_view(), name='edit'),


test_views.py
response = self.client.get(f'/edit/{bulletin.slug}')

我相信这就是问题所在。

您将视图 url 定义为带有斜杠的 end,但是当您在测试函数中请求 url 时,您使用的 url 没有 末尾的斜杠。

Django 以 301 将您重定向到正确的 url,with 最后一个斜杠。

© www.soinside.com 2019 - 2024. All rights reserved.