我正在为我作为课程一部分编写的 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,它会显示一个错误页面。
最后,以防万一它还不是很明显,我应该补充一下我是新手。所以如果上面有什么真的很愚蠢的事情向你跳来跳去,请保持温柔!
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,因为在幕后,此方法实际上获得了您声明的相同路径。
创建用户时,您将通过文本字符串设置密码。但是,此密码在存储在
user.password
之前会经过哈希处理
然后当您尝试使用存储的散列密码
user.password
登录时,提供的密码在比较之前再次散列。这将失败并可能导致重定向。
试试
self.client.login(username=self.user_1.username,
password="test")
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 最后一个斜杠。