Views 在blog/views.py
文件中增加新的视图类BlogDetailView
1 2 3 4 5 6 7 8 9 10 from django.views.generic import ListView, DetailView from . models import Post class BlogListView(ListView): model = Post template_name = 'home.html' class BlogDetailView(DetailView): model = Post template_name = 'post_detail.html'
默认情况下,DetailView 会提供一个上下文对象object
或小写的模型(model)名字post
用在模板文件中 DetailView 需要一个主键或slug作为标识符。后面详述…
Templates 新建templates/post_detail.html
文件,内容如下:
1 2 3 4 5 6 7 8 {% extends 'base.html' %} {% block content %} <div class="post-entry"> <h2>{{ post.title }}</h2> <p>{{ post.body }}</p> </div> {% endblock content %}
URLs 修改blog/urls.py
文件,代码如下:
1 2 3 4 5 6 7 8 from django.urls import path from . import views urlpatterns = [ path('', views.BlogListView.as_view(), name='home'), path('post/<int:pk>/', views.BlogDetailView.as_view(), name='post_detail'), ]
再次运行程序,访问页面http://127.0.0.1:8000/post/1/
,显示如下:
更新templates/home.html
文件,添加页面链接,代码如下:
1 2 3 4 5 6 7 8 9 10 {% extends 'base.html' %} {% block content %} {% for post in object_list %} <div class="post-entry"> <h2><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h2> <p>{{ post.body }}</p> </div> {% endfor %} {% endblock content %}
Tests 增加针对模型和视图的测试代码,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 from django.test import TestCase, Client from django.contrib.auth import get_user_model from django.urls import reverse from .models import Post class BlogTests(TestCase): def setUp(self): self.user = get_user_model().objects.create_user( username = 'testuser', email = 'test@email.com', password = 'secret' ) self.post = Post.objects.create( title = 'A good title', body = 'Nice body content', author = self.user, ) def test_string_representation(self): post = Post(title='A sample title') self.assertEqual(str(post), post.title) def test_post_content(self): self.assertEqual(f'{self.post.title}', 'A good title') self.assertEqual(f'{self.post.author}', 'testuser') self.assertEqual(f'{self.post.body}', 'Nice body content') def test_post_list_view(self): response = self.client.get(reverse('home')) self.assertEqual(response.status_code, 200) self.assertContains(response, 'Nice body content') self.assertTemplateUsed(response, 'home.html') def test_post_detail_view(self): response = self.client.get('/post/1/') no_response = self.client.get('/post/1000/') self.assertEqual(response.status_code, 200) self.assertEqual(no_response.status_code, 404) self.assertContains(response, 'A good title') self.assertTemplateUsed(response, 'post_detail.html')
执行如下命令,运行测试用例: