课程:Django入门项目 - 论坛系统
打卡时间:2018.5.8
目录
【Django】入门实践指南之环境搭建|第0篇
【Django】入门实践指南之系统设计|第1篇
【Django】入门实践指南之模型设计|第2篇
【Django】入门实践指南之模板引擎|第3篇
【Django】入门实践指南之测试&静态文件配置|第4篇
【Django】入门实践指南之Admin&URL分发|第5篇
【Django】入门实践指南之模板复用&表单处理|第6篇
前言
本篇学习模板复用和表单的一些知识,这篇文章比较长。耐心读完会有收获的。
一、模板复用
之前我们创建的两个home.html
和topic.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.html
和topic.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的使用方法。由代码较多没有整理,请查看:表单处理
网友评论