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

2018-05-08  本文已影响30人  繁华落尽丶lee

课程: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的使用方法。由代码较多没有整理,请查看:表单处理

上一篇下一篇

猜你喜欢

热点阅读