【Django】入门实践指南之模板复用&表单处理|第6篇

课程:Django入门项目 - 论坛系统
打卡时间:2018.5.8

目录

【Django】入门实践指南之环境搭建|第0篇
【Django】入门实践指南之系统设计|第1篇
【Django】入门实践指南之模型设计|第2篇
【Django】入门实践指南之模板引擎|第3篇
【Django】入门实践指南之测试&静态文件配置|第4篇
【Django】入门实践指南之Admin&URL分发|第5篇
【Django】入门实践指南之模板复用&表单处理|第6篇

前言

本篇学习模板复用和表单的一些知识,这篇文章比较长。耐心读完会有收获的。

一、模板复用

之前我们创建的两个home.htmltopic.html。他们之间存在一些相同的内容,如果单独创建文件少还可以,如果有几十个页面甚至上百个页面,维护起来就相当麻烦了。这是就需要复用技术。

通过编写一个母模板,包含页面所共有的内容。其他模板继承自母模板。

templates中创建名为base.html的文件。

{% load static %}<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Django Boards {% endblock %}</title>
    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
    <div class="container">
        <ol class="breadcrumb my-4">
            {% block breadcrumb %}
            {% endblock %}
        </ol>
        {% block content %}
        {% endblock %}
    </div>
</body>
</html>

以上就是母版页,其他模板都需要继承该模板。模板中{% block %}标签。它用于在模板中保留一个空间,子模板可以在其中插入代码和HTML。

例如:{% block title %}是接收title的,母版中给出了默认值。

下面重写之前的两个模板: home.htmltopic.html

{#继承自base.html#}
{% extends 'base.html' %}

{#添加头部导航标签#}
{% block breadcrumb %}
    <li class="breadcrumb-item active">Boards</li>
{% endblock %}

{#页面内容#}
{% block content %}
<table class="table">
            <thead class="">
            <tr>
                <th>Board</th>
                <th>Posts</th>
                <th>Topics</th>
                <th>Last Post</th>
            </tr>
            </thead>
            <tbody>
                {% for board in boards %}
                    <tr>
                        <td>
{#                            进入board_topics传递参数pk #}
                            <a href="{% url 'board_topics' board.pk%}">{{ board.name }}</a>
                            <small class="text-muted d-block">{{ board.desc }}</small>
                        </td>
                        <td class="align-middle">0</td>
                        <td class="align-middle">0</td>
                        <td></td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

{% endblock %}

topic界面

{% extends 'base.html' %}

{% block title %}
    {{ board.name }} - {{ block.super }}
{% endblock %}

{% block breadcrumb %}
    <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li>
    <li class="breadcrumb-item active">{{ board.name }}</li>
{% endblock %}

{% block content %}

{% endblock %}

修改完成后,可以验证一下是否存在错误。

执行python manage.py test

二、表单处理

表单用来处理用户的输入。下面看一个例子吧!

新建一个路由,命名为new_topic:

{% extends 'base.html' %}

{% block title %}
Start a New Topic
{% endblock %}

{% block breadcrumb %}
    <li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li>
    <li class="breadcrumb-item"><a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a></li>
    <li class="breadcrumb-item active">New topic</li>
{% endblock %}

{% block content %}

{% endblock %}

new_topic进行测试

class NewTopicTests(TestCase):
    def setUp(self):
        Board.objects.create(name='Django', desc='Django board')

    def test_new_topic_view_success_status_code(self):
        url = reverse('new_topic', kwargs={'pk': 1})
        response = self.client.get(url)
        self.assertEquals(response.status_code, 200)

    def test_new_topic_view_not_found_status_code(self):
        url = reverse('new_topic',kwargs={'pk': 99})
        response = self.client.get(url)
        self.assertEquals(response.status_code, 404)

    def test_new_topic_url_resolves_new_topic_view(self):
        view = resolve('/boards/1/new/')
        self.assertEquals(view.func, new_topic)

    def test_new_topic_view_contains_link_back_top_board_topics_view(self):
        new_topic_url = reverse('new_topic', kwargs={'pk': 1})
        board_topic_url = reverse('board_topics', kwargs={'pk': 1})
        response = self.client.get(new_topic_url)
         self.assertContains(response, 'href="{}"'.format(board_topic_url))

setUp:创建一个测试中使用的 Board 实例
test_new_topic_view_success_status_code:检查发给 view 的请求是否成功
test_new_topic_view_not_found_status_code:检查当 Board 不存在时 view 是否会抛出一个 404 的错误
test_new_topic_url_resolves_new_topic_view:检查是否正在使用正确的 view
test_new_topic_view_contains_link_back_to_board_topics_view:确保导航能回到 topics 的列表

运行python manage.py test,查看测试结果。

new_topic添加表单。


{% block content %}
    <form method="post">
    {% csrf_token %}
    <div class="form-group">
        <label for="id_subject" class="">Subject</label>
        <input type="text" class="form-control" id="id_subject" name="subject">
    </div>
    <div class="form-group">
        <label for="id_message" class="">Message</label>
        <textarea name="message" id="id_message" rows="5" class="form-control"></textarea>
    </div>
    </form>
{% endblock %}

csrf_token模板标签,它是与其他表单数据一起提交的隐藏字段。

获取数据用户输入的数据。

def new_topic(request, pk):
    board = get_object_or_404(Board, pk=pk)

    if request.method == 'POST':
        subject = request.POST['subject']
        message = request.POST['message']
        user = User.objects.first() # 临时登陆账户

        topic = Topic.objects.create(
            subject = subject,
            board = board,
            starter = user
        )
        post = Post.objects.create(
            message = message,
            topic = topic,
            created_by = user
        )
        return redirect('board_topics', pk=board.pk) # 重定向到topic页
    return render(request, 'new_topic.html', {'board': board})

参考:表单处理
由于代码较多,这里不粘贴代码。

三、创建表单的正确方式

Forms API创建表单,在django.forms模块中。两种表单类型:
forms.Form: 通用表单实现
forms.ModelFrom:Form的子类,它与Model相关联。

boards/forms.py

from django import forms
from .models import Topic

class NewTopicForm(forms.ModelForm):
    message = forms.CharField(widget=forms.Textarea(), max_length=4000)

    class Meta:
        model = Topic
        fields = ['subject', 'message']

这是我们的第一个 form。它是一个与 Topic model 相关联的 ModelForm。Meta 类里面 fields 列表中的 subject 引用 Topic 类中的 subject field(字段)。现在注意到我们定义了一个叫做 message 的额外字段。它用来引用 Post 中我们想要保存的 message。

四、小结

本篇学习表单的基本用法,Form API的使用方法。由代码较多没有整理,请查看:表单处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Forms(表单) 用来处理我们的输入。这在任何 web 应用或者网站中都是很常见的任务。标准的做法是通过 HTM...
    冰321阅读 4,463评论 0 0
  • 《盗火线》 这部影片吸引人的不是剧情不是刺激的枪战而是其中的每一个人物都真实且鲜活,尽管他们戏份或多或少。...
    妄谈疯话阅读 2,338评论 0 0
  • 讲个单位的奇葩吧 A:把这个给我用A4纸复印, B:好, 历经千辛万难,终于知道怎么用打印机,然而,可能他理解的A...
    免扰_飞行模式阅读 741评论 0 0
  • 今天,看到一句话“谈恋爱要找自己爱的人,结婚要找爱自己的人。”我应该感到幸运吧,mr.李今天中午一点的高铁,为了能...
    Fantali阅读 1,098评论 0 0
  • 步骤: 1.先制作中间的大叶子,先融合至三分之一,杯子倾斜一些,然后开始晃动制作第一个叶子,要预留空间给余后动作。...
    神秘嘉宾l阅读 2,701评论 0 1