Django 搭建简易博客之二 - 完成前端渲染

Views 和路由设置

由之前的教程,我们得知网页的逻辑如下:

request 进来 -> 从服务器获取数据 -> 处理数据 -> 把网页呈现出来

url 设置相当于从客户端先个服务器发出 request 请求的入口,并用来知名要调用的程序逻辑。
views 用来处理程序逻辑,然后传递数据到 template。
template 一般为 html + css 的形式,主要是呈现给用户的表现形式。
我们已经完成了底层数据(文章列表)的基础。所以由内向外,开始构建数据处理。下面我们来编辑 views.py 的逻辑并规划路由。

编辑 my_blog/article/views.py 中编写简单的逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.shortcuts import render
from django.http import HttpResponse
from article.models import Article

# Create your views here.
def home(request):
return HttpResponse("Hello World, Django")

def detail(request, my_args):
post = Article.objects.all()[int(my_args)]
str = ("title = %s, category = %s, date_time = %s, content = %s"
% (post.title, post.category, post.date_time, post.content))
return HttpResponse(str)

我们在 views.py 中增加了一些包。其中有 HttpResponse 用于处理以字符串形式的 response 。另外我们还需要将之前创建的 Article 这个 model 引入进来。因为我们需要描述文章,用这个 model 再适合不过。

在 home 方法中,直接返回一个字符串形式的 response,用于测试使用。而在 detail 方法中,我们通过与数据和的交互,来将文章列表返回给用户。

也许你会问,这里的 my_args 我们应该如何获取呢?其实该参数可以直接从路由的正则表达式中可以直接拿出,下面我们编辑路由。编辑 my_blog/my_blog/urls.py:

1
2
3
4
5
6
7
8
9
from django.conf.urls import include, url
from django.contrib import admin
from article import views as article_views

urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$', article_views.home, name = 'home'),
url(r'^(?P<my_args>\d+)/$', article_views.detail, name = 'detail'),
];

^(?P<my_args>\d+)/$ 这个正则表达式的意识是将传入的一位或者多为数字作为参数传递到 views 中的 detail 方法作为参数。其中 ?P<my_args> 定义名称用于标识匹配的内容。

由于此时我们数据库中只有之前创建的一条记录,所以当 my_args = 0 时才能获取成功。以下是效果图:

编写 Template,优化视觉体验

到目前为止,我们完成了后端数据显示到页面上的流程,下面我们开始涉及到 HTML 代码,使得博客通过 HTML + CSS 的渲染后,漂亮的显示到浏览器上。

我们使用 Pure 这个轻量级前端响应式框架来展现我们的 blog。

我们在 article 目录下创建 templates 目录:

1
$ mkdir article/templates

然后在该目录下建立模板基础文件 base.html:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="A layout example that shows off a blog page with a list of posts.">

<title>Shiyanlou Blog</title>
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/803/blog.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/803/grids-responsive-min.css">
<link rel="stylesheet" href="http://labfile.oss.aliyuncs.com/courses/803/pure-min.css">
</head>
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<div class="header">
<h1 class="brand-title">Shiyanlou Blog</h1>
<nav class="nav">
<ul class="nav-list">
<li class="nav-item">
<a class="pure-button" href="#">Github</a>
</li>
<li class="nav-item">
<a class="pure-button" href="#">Weibo</a>
</li>
</ul>
</nav>
</div>
</div>

<div class="content pure-u-1 pure-u-md-3-4">
<div>
{% block content %}
{% endblock %}
<div class="footer">
<div class="pure-menu pure-menu-horizontal pure-menu-open">
<ul>
<li><a href="#">About Me</a></li>
<li><a href="#">Twitter</a></li>
<li><a href="#">GitHub</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>

</body>
</html>

在这个文件中,首先我们导入 pure-min.css、grids-responsive-min.css、blog.css 这三个 css 样式集。这个是为大家预先准备好的三个文件,用于控制我们的博客样式。在文章集合显示的部分,我们发现了如下代码:

1
2
{% block content %}
{% endblock %}

这两个字段是 Django 中模板未见自带的关键字,它的作用是 用来被其他继承此基类模板进行重写。所以我们接下来要编辑所继承的那个超集模板。

我们在 templates 目录下继续添加 home.html 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{% extends "base.html" %}

{% block content %}
<div class="posts">
{% for post in post_list %}
<section class="post">
<header class="post-header">
<h2 class="post-title">{{ post.title }}</h2>

<p class="post-meta">
Time: <a class="post-author" href="#">{{ post.date_time }}</a> <a class="post-category post-category-js" href="#">{{ post.category }}</a>
</p>
</header>

<div class="post-description">
<p>
{{ post.content }}
</p>
</div>
</section>
{% endfor %}
</div><!-- /.blog-post -->
{% endblock %}

我们来解释一下这个文件:

1
2
# `{% for <element> in <list> %}` 与 `{% endfor %}` 成对存在, 这是template 中提供的 for 循环 tag
# `{% if <elemtnt> %} {% else %} {% endif %}` 是 template 中提供的 if 语句 tag

所以我们要往其中加入 post 的数据。继续编辑 views.py,修改 home 方法:

1
2
3
def home(request):
post_list = Article.objects.all() #获取全部的Article对象
return render(request, 'home.html', {'post_list' : post_list})

大功告成。我们重新访问 http://127.0.0.1:1103/ 可以看见在开篇实现的效果:

环境中所使用的 firefox 浏览器似乎对渲染响应式布局有些问题,在尺寸过宽的情况下无法显示 pure 的布局效果。但是在窄屏(适用于移动端)模式下却显示正常。(╯‵□′)╯︵┻━┻;上图为窄屏模式下的效果图。