Django类视图测试:编辑页返回301而非200的问题排查
Django编辑页视图测试返回301状态码问题排查
问题说明
在课程项目中为Django类视图编写测试,编辑页要求用户登录且待编辑内容为该用户创建。测试时已实例化模型和用户,登录后请求编辑页,预期响应状态码200,但始终返回301。
相关代码
urls.py - 编辑页路径
path('edit/<slug:slug>/', views.EditBulletin.as_view(), name='edit'),
models.py - Bulletin模型
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 - EditBulletin视图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 - 测试代码
@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的
likes多对多字段,未解决问题
问题原因及修复方案
1. URL末尾缺少斜杠导致301重定向
urls.py中编辑页路径末尾带有斜杠('edit/<slug:slug>/'),但测试中请求的URL是'/edit/{bulletin.slug}',末尾无斜杠。Django默认开启APPEND_SLASH设置,会自动将无斜杠的URL重定向到带斜杠的版本,因此返回301。
修复:请求URL添加末尾斜杠:
response = self.client.get(f'/edit/{bulletin.slug}/')
2. 登录密码错误
User.objects.create_user会自动哈希存储密码,self.user_1.password是哈希后的字符串,而非明文的'test'。测试中用哈希值登录会失败,导致用户未真正登录。
修复:登录时直接使用明文密码:
self.client.login(username=self.user_1.username, password='test')
3. Bulletin状态不匹配导致404
视图中查询集是Bulletin.objects.filter(status=1),但模型中status默认值为0,测试创建的Bulletin未指定status,因此不符合查询条件,即使URL正确也会返回404。
修复:创建Bulletin时指定status为1:
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, status=1)
修复后的完整测试代码
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='test') # 创建status为1的Bulletin 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, status=1) # 请求带末尾斜杠的URL response = self.client.get(f'/edit/{bulletin.slug}/') self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'edit_bulletin.html')
内容的提问来源于stack exchange,提问作者ClubShrimp
相关产品推荐
相关产品推荐

