一篇博客,要将其找出来,就需要有一个唯一的标识。Django 的模型中默认有一个唯一的且未自增长的主键,即 id 字段,我们可以以此为关键字来定位一篇博客。

1. 编辑路由

编辑myblog/urls.py,新增内容:

from django.contrib import admin
from django.urls import path
from blog.views import get_blogs,get_detail
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',get_blogs,name='blog_get_blogs'),
    path('detail/<blog_id>',get_detail,name='blog_get_detail'),
]

2. 生成和处理评论

Django Form 能帮助我们快速实现这一需求。构建一个表单,新建文件 blog/forms.py

from django import forms
class CommentForm(forms.Form):
"""评论表单"""
name = forms.CharField(label='称呼', max_length=16, error_messages={
'required': '请填写您的称呼',
'max_length': '称呼太长'
})
email = forms.EmailField(label='邮箱', error_messages={
'required': '请填写您的邮箱',
'invalid': '邮箱格式不正确'
})
content = forms.CharField(label='评论内容', error_messages={
'required': '请填写您的评论内容',
'max_length': '评论内容太长'
})

代码中定义了一个评论表单的类并根据需求定义了三个字段:称呼、邮箱和评论内容。这样我们就能利用它来快速生成表单并验证用户的输入。

3. 编辑视图,修改如下:

Blog/views.py

from .forms import CommentForm
from django.http import Http404 def get_detail(request, blog_id):
try:
blog = Blog.objects.get(id=blog_id)
except Blog.DoesNotExist:
raise Http404 if request.method == 'GET':
form = CommentForm()
else:
form = CommentForm(request.POST)
if form.is_valid():
cleaned_data = form.cleaned_data
cleaned_data['blog'] = blog
Comment.objects.create(**cleaned_data) ctx = {
'blog': blog,
'comments': blog.comment_set.all().order_by('-created'),
'form': form
}
return render(request, 'blog-detail.html', ctx)
  • get_detail() 视图函数首先利用传入的 blog_id 到数据库中查询该条博客记录。注意这使用了 try 块,因为 model.objects.get() 方法会在未能查询到数据的情况下抛出 model.DoesNotExist 的异常。如果没有对此异常进行拦截的话,就会导致服务器 500 错误,这显然不是用户想看到的。而是应该在发生此错误的情况下通知用户“你要访问的内容未能找到”。一般情况下网站都会在这个时候向用户抛出一个 404 错误并定义一些“生动有趣”的话语来提示用户同时又不会显得太突兀而让用户产生反感;
  • 中间一个部分是对表单的初始化和校验处理。这里会涉及到 HTTP 的 GET 请求和 POST 请求。一般来说,GET 请求用于获取数据,而 POST 请求则为提交数据。这里也遵循此一般约定,在用户做 GET 请求时,仅初始化一个空表单供用户填写;而如果是 POST 请求的话,则在初始化的同时将用户传入的数据传入。用户传入的数据会收集在 request.POST 中,是一个类似于字典的对象。接下来是调用 form 类的 is_valid() 方法来对用户输入做校验,如果校验成功,则创建一条评论记录;
  • ctx 依然是要传入到模板的上下文参数,其中 blog 是博客对象,comments 是利用 ORM 的反查方法找到当前博客包含的所有评论,并以发布时间的倒序方式进行排列,另外还有一个 form,是之前定义的 CommentForm 的实例化对象,它用于初始化评论表单。

4. 定义博客内容模板templates/blog-detail.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ blog.title }}</title>
<style>
.blog {
padding: 20px 0px;
}
.blog .info span {
padding-right: 10px;
}
.blog .summary {
padding-top: 20px;
}
</style>
</head>
<body> <div class="header">
<span><a href="{% url 'blog_get_blogs' %}">博客</a> - <a href="{% url 'blog_get_detail' blog.id %}">{{ blog.title }}</a></span>
</div> <div class="content">
<div class="blog">
<div class="title">
<a href="#"><h2>{{ blog.title }}</h2></a>
</div>
<div class="info">
<span class="category" style="color: #ff9900;">{{ blog.category.name }}</span>
<span class="author" style="color: #4a86e8">{{ blog.author }}</span>
<span class="created" style="color: #6aa84f">{{ blog.created|date:"Y-m-d H:i" }}</span>
</div>
<div class="summary">
{{ blog.content }}
</div>
</div>
<div class="comment">
<div class="comments-display" style="padding-top: 20px;">
<h3>评论</h3>
{% for comment in comments %}
<div class="comment-field" style="padding-top: 10px;">
{{ comment.name }} 说: {{ comment.content }}
</div>
{% endfor %}
</div>
<div class="comment-post" style="padding-top: 20px;">
<h3>提交评论</h3>
<form action="{% url 'blog_get_detail' blog.id %}" method="post">
{% csrf_token %}
{% for field in form %}
<div class="input-field" style="padding-top: 10px">
{{ field.label }}: {{ field }}
</div>
<div class="error" style="color: red;">
{{ field.errors }}
</div>
{% endfor %}
<button type="submit" style="margin-top: 10px">提交</button>
</form>
</div>
</div>
</div> </body>
</html>
  • {% url 'blog_get_blogs' %} 可以看作是 reverse 方法的“模板语言”版,其作用是根据 URLConf 中的 name 定义对 url 进行反解析,转换成真实的 URL 地址。比如这里在转换之后会变成 “/”。如果所指定的 url 定义中包含参数,则需要将参数跟在后面,如 {% url 'blog_get_detail' blog.id %};
  • 观察表单的内容,{% csrf_token %} 用于防跨域请求,可参考一些关于 CSRF 相关的资料并阅读 Django 官方文档关于这一块实现的描述。{% for field in form %}{% endfor %} 是对表单的各个 field 进行迭代并生成相应的表单元素,并对校验过程中出现的错误进行显示以提示用户做相应的修改。最后还生成一个 button 用于点击提交评论。

5. 修改主页的博客标题链接

将templates/blog-list.html中之前设置的#改为如下内容:

{% url 'blog_get_detail' blog.id %}

最新文章

  1. 一切从“简”,解放IT运维人员
  2. ExceptionLess新玩法 — 记日志
  3. CSS font 复合属性的顺序
  4. Bootstrap carousel轮转图的使用
  5. 【Leetcode】【Hard】Insert Interval
  6. linux下批量查找/替换文本内容
  7. 面向侧面的程序设计AOP-------《三》.Net平台AOP技术概览
  8. bzoj 3551 [ONTAK2010]Peaks加强版(kruskal,主席树,dfs序)
  9. IntelliJ IDEA 的Project structure说明
  10. Apache经常使用配置
  11. wing 5.0 注册机
  12. ajax表单提交全路径
  13. 你是否听过 TypeScript?
  14. 《Effective C++》实现:条款26-条款31
  15. [转]Database Transactions in Laravel
  16. 日志记录模块logging
  17. 前端 ---jQuery的补充
  18. Latex 表格(跨行、跨列、背景加灰)new
  19. MySQL: Connection Character Sets and Collations
  20. JVM内存管理及GC机制

热门文章

  1. 点击 table 单元格 取值
  2. How To:配置Openfiler磁盘
  3. Getmemory问题
  4. THUSC2019 退役记
  5. 模拟Spring容器的getBean方法(Maven工程)
  6. input chrome下输入之后背景变为黄色的解决办法
  7. BUAA_OO_博客作业三
  8. 【Codeforces 1114D】Flood Fill
  9. H5音乐播放器
  10. zookeeper监控之taokeeper