Django搭建个人博客:改写View视图

7348阅读 · 17评论 · 2018/09/11发布   前往评论

改写视图函数

上一章我们感受了视图的工作流程。

为了让视图真正发挥作用,改写article/views.py中的article_list视图函数:

article/views.py

from django.shortcuts import render

# 导入数据模型ArticlePost
from .models import ArticlePost

def article_list(request):
    # 取出所有博客文章
    articles = ArticlePost.objects.all()
    # 需要传递给模板(templates)的对象
    context = { 'articles': articles }
    # render函数:载入模板,并返回context对象
    return render(request, 'article/list.html', context)

代码同样很直白,分析如下:

  • from .models import ArticlePostmodels.py中导入ArticlePost数据类

  • ArticlePost.objects.all()是数据类的方法,可以获得所有的对象(即博客文章),并传递给articles变量

  • context定义了需要传递给模板的上下文,这里即articles

模板的概念马上就要讲。

  • 最后返回了render函数。它的作用是结合模板和上下文,并返回渲染后的HttpResponse对象。通俗的讲就是把context的内容,加载进模板,并通过浏览器呈现。

render的变量分解如下:

  • request是固定的request对象,照着写就可以
  • article/list.html定义了模板文件的位置、名称
  • context定义了需要传入模板文件的上下文

视图函数这样就写好了。

编写模板(template)

在前面的视图中我们定义了模板的位置在article/list.html,因此在根目录下新建templates文件夹,再新建article文件夹,再新建list.html文件,即:

my_blog
  ...
├─article
  ...
└─my_blog
  ...
└─templates
    └─ article
        └─ list.html

细心的你肯定注意到了,之前的Django文件后缀都是.py,代表Python文件;这里的模板文件后缀是.html,这又是什么呢?

HTML是一种用于创建网页的标记语言。它被用来结构化信息,标注哪些文字是标题、哪些文字是正文等(当然不仅仅这点功能)。也可以简单理解为“给数据排版”的文件,跟你写文档用的Office Word一样一样的 。

list.html文件中写入:

templates/article/list.html

{% for article in articles %}
    <p>{{ article.title }}</p>
{% endfor %}

Django通过模板来动态生成HTML,其中就包含描述动态内容的一些特殊语法:

  • {% for article in articles %}articles为视图函数的context传递过来的上下文,即所有文章的集合。{% for %}循坏表示依次取出articles中的元素,命名为article,并分别执行接下来操作。末尾用{% endfor %}告诉Django循环结束的位置。

  • 使用.符号来访问变量的属性。这里的article为模型中的某一条文章;我们在前面的ArticlePost中定义了文章的标题叫title,因此这里可以用article.title来访问文章的标题。

  • <p>...</p>即为html语言,中间包裹了一个段落的文字。

在上一章中已经定义好了urls.py,因此不再需要改动了。

一切都很好,深吸一口气。保存所有文件,在浏览器中输入地址http://127.0.0.1:8000/article/article-list/,得到以下错误:

似乎成功从来都不会很顺利。

错误分析

虽然出错了,好在Django提供了非常完善的错误处理系统,方便开发者快速找到Bug的蛛丝马迹。

第一行就醒目地提示:TemplateDoesNotExist,说明Django没有找到list.html这个文件。仔细检查目录、文件的名称无误,没问题就往下继续看。

然后发现有这么两行:

...django\contrib\admin\templates\article\list.html (Source does not exist)
...django\contrib\auth\templates\article\list.html (Source does not exist)

似乎Django在这两个位置搜索(没有在刚创建的templates目录),没有发现需要的文件,然后返回了“未发现模板文件”的错误。

定位了问题的所在,接下来就是在如何“告诉”Django我的模板位置呢?

答案就在settings.py中了,它保存了Django项目的各种初始配置

打开并找到这一段,加入代码os.path.join(BASE_DIR, 'templates')

my_blog/settings.py

TEMPLATES = [
    {
        ...
        # 定义模板位置
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
    },
]

这就是说模板文件在项目根目录的templates文件夹中,去找找吧。

保存文件,重新启动服务器:

成功!

虽然简陋,但是已经走通了MTV(model、template、view)环路。

不要激动,精彩的还在后面。

三个工具

此节为 2019/6/1 新增

读者在开发中每天都会遇到各种各样的问题。

解决问题的方法很多,其中有三个工具非常的有效,着重提一下:

  • Django报错页面:就是上面出现的那个黄黄的报错页面啦。Django报错页面在大多数情况下都能准确的判断错误类型、错误抛出的位置、甚至是解决方案。读者千万不要觉得读这么多英文好麻烦啊,其实重点就那么几句话。

  • 浏览器控制台:如果你用的浏览器是Chrome,那么打开控制台的快捷键是Ctrl + Shift + i。控制台里又有两个子页面很常用:Elements这里列出整个网页源码,可以在这里查看css样式的继承情况、容器的相互关系,甚至可以动态修改源码查看效果。Console类似运行Django的命令行。如果浏览器运行网页时遇到故障(比如404 未找到资源403 服务器通讯失败500 服务器内部错误),都会在这里提示。以后还可以在JavaScript代码中用console.log()指令将感兴趣的内容打印到Console中查看。非常非常有用

  • print():很多读者在写纯Python代码时知道用print()来查找bug,到Django中反而不会了。其实Django也是一样的,在视图函数中写的print()会打印到命令行中。

依靠这三个工具,基本上就能给出90%以上的错误信息了。接下来就是把错误的关键词放到Google、Bing这些地方去搜索答案了。

再强调一下敲代码要细心。我发现很多读者的bug都是源自于拼写、缺行漏行这种让人沮丧的错误。

总结

本章我们重写了视图,编写了简单的模板,和前面的模型成功关联起来。

下一章将学习编写一个漂亮的网页模板。




本文作者: 杜赛
发布时间: 2018年09月11日 - 21:18
最后更新: 2019年06月02日 - 10:06
知识共享许可协议   转载请保留原文链接及作者


登录 后回复

共有17条评论

avatar
Python 么么哒! 4

你好!本章有个问题要请教:我按照你的教程,建模后都还好,一直到输入(http://127.0.0.1:8000/article/article-list/)访问文章标题、内容、作者时一直报错404.然后也无法显示出hello world,错误也是一样。因为找不到上传截图地方,我将报错信息贴到下面,请赐教(我的环境是:win7 x64    python3.5.3    django2.1):

Page not found (404)

Request Method:GETRequest URL:http://127.0.0.1:8000/article/article-list/

Using the URLconf defined in my_blog.urls, Django tried these URL patterns, in this order:

1. admin/

2. article article-list/ [name='article_list']

The current path, article/article-list/, didn't match any of these.

You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.

刚才我又修改settings.py 里的

DEBUG = False

ALLOWED_HOSTS = ['*',]

出现

Not Found

The requested URL /article/article-list/ was not found on this server.

 

9个月前 回复


avatar
Python Python 么么哒! 3

今天又尝试了下。问题解决。原因是自己粗心:my_blog/urls.py  里的

path('article/', include('article.urls', namespace= 'article')),

article 没有加 /,还有 list.html 里的 endfor  中间有空格造成的。

9个月前 回复


avatar
杜赛 [博主] Python 么么哒! 4

嗯嗯,解决了就好。也可以参考我的github中的代码示例。

另外考虑到安全问题,网站的回复暂时没开上传图片的权限,实在需要展示图片的话就Email我吧。

9个月前 回复


avatar
Jenychen1996 么么哒! 4

from django.shortcuts import render

# 导入数据模型ArticlePost
from .models import ArticlePost

# Create your views here.
def article_list(request):
    # 取出所有文章
    articles = ArticlePost.objects.all()  # 此处的objects对象,我访问不到,打开页面后不显示任何内容,请问是何原因?
    # 需要传递给模板(templates)的对象
    context = {'article': articles}
    # render 函数:载入模板,并返回context对象
    return render(request, 'article/list.html', context)

 

7个月前 回复


avatar
杜赛 [博主] Jenychen1996 么么哒! 4

报错信息的内容说了什么?

数据迁移正确吗?

模板写得正确吗?

7个月前 回复


avatar
Jenychen1996 杜赛 [博主] 么么哒! 4

没有报错。页面显示为空白。

后台我进去了,我写的东西是存在的。

迁移没有报错。

模板是按照你的写的、我检查过了。

7个月前 回复


avatar
Jenychen1996 Jenychen1996 么么哒! 4

from django.db import models
# 导入内建的User模型
from django.contrib.auth.models import User
# timezone用于处理时间相关事务
from django.utils import timezone

# Create your models here.
# 博客文章数据模型
class ArticlePost(models.Model):
    # 文章作者。参数 on_delete 用于指定数据删除的方式
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    # 文章标题。models.CharField 为字符串字段,用于保存较短的字符串。
    title = models.CharField(max_length=100)

    # 文章正文。保存大量文本用TextField
    body = models.TextField()

    # 文章创建时间。
    created = models.DateTimeField(default=timezone.now)

    # 文章更新时间。修改时自动写入当前时间。
    updated = models.DateTimeField(auto_now=True)

    # 内部类class Meta用于给model 定义元数据
    class Meta:
        # ordering 指定模型返回的数据的排列顺序
        # '-created' 表明数据应该以倒序排列
        ordering = ('-created', )

    # 函数 __str__ 定义当用户调用str()方法时的返回值内容
    def __str__(self):
        # 将文章标题返回
        return self.title

 

7个月前 回复


avatar
zpz Jenychen1996 么么哒! 4

context = {'article': articles}
这一行写错了,改为
context = {'articles': articles}
少加了个s

7个月前 回复


avatar
Jenychen1996 zpz 么么哒! 4

多谢兄弟,成功了。

7个月前 回复


avatar
杜赛 [博主] zpz 么么哒! 3

yes看得很仔细

7个月前 回复


avatar
zpz 杜赛 [博主] 么么哒! 4

7个月前 回复


avatar
zpz Jenychen1996 么么哒! 4

7个月前 回复


avatar
CearlERO zpz 么么哒! 4

context是数据字典哈,所以HTML里面for article in  articles (这个articles就是字典里的键哈),是这样吗?

3个月前 回复


avatar
杜赛 [博主] CearlERO 么么哒! 3

是的,可以这样理解

3个月前 回复


avatar
ac1864 么么哒! 4

学习了好几次Django都是卡在模板上面,都有点心理阴影了。

希望这次能够通关。

今天学完了,“前言”,开发环境,创建app,编写model,初探view.

明天花用一整天搞定模板。。

5个月前 回复


avatar
杜赛 [博主] ac1864 么么哒! 4

模板说白了就是html+css+javascript,是另外一套知识体系。

你可能得好好阅读bootstrap的官方文档才能理解。

不过没关系,模板先抄也问题不大。慢慢理解。

5个月前 回复


avatar
zuolei 么么哒! 4
本回复已被 zuolei 删除

5个月前 回复