zoukankan      html  css  js  c++  java
  • Django学习案例一(blog):六. 开发博客内容页面

    一篇博客,要将其找出来,就需要有一个唯一的标识。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 %}
  • 相关阅读:
    kubectl 命令详解
    codeforce344 C report
    poj3041 建图+最小顶点覆盖(最大匹配数)
    poj1637 混合欧拉回路的判定
    poj1149 最大流好题 难在建图 好题
    targan 算法模板
    poj2186 强连通分量 targan算法的应用
    poj2723 2分 + 2-sat
    poj3061 尺取法
    poj3207 2-sat基础题
  • 原文地址:https://www.cnblogs.com/summyfly/p/7808846.html
Copyright © 2011-2022 走看看