谈谈Python之Django搭建企业级官网(第四篇上)

扶醉桌前 提交于 2019-11-26 03:19:50

转载请注明来源地址和原作者(CFishHome)

前沿

本篇文章将介绍模板相关的内容,例如:DTL模板语法(变量、模板标签、过滤器、自定义过滤器)。只要一步一步跟着一起操作,我相信模板这一块的内容毫无难度,就好像学习MarkDown一样好学好用。在此,因为前不久学校有很多事要处理,所以学习笔记耽搁了几天,趁国庆好好补补落下的内容,还有本篇DTL语法涉及众多,所以决定分上中下篇来讲解和总结。

学前工作

我们先创建一个名为my_template的新Django项目。因为这篇内容涉及的是模板内容,跟app关系不大,所以在这里我就不创建一个app来进行URL映射了,而是直接在my_template主包
里添加一个views.py文件进行URL映射。整体框架如下图所示:
谈谈Python之Django搭建企业级官网(第四篇上)
(1)为views.py添加以下代码:

from django.http import HttpResponse

def index(request):
    return HttpResponse("首页")

(2)修改urls.py代码如下:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name="index")
]

运行项目,能成功访问127.0.0.1:8000,好了学前工作准备完毕,下面正式进入模板的学习。

模板

在前面的学习中,我们编写的视图函数只是直接返回文本,例如:HttpResponse("首页"),而在实际生产环境中其实很少这样用,因为实际的页面大多是带有样式的HTML代码,这可以让浏览器渲染出非常漂亮的页面。目前市面上有非常多的模板系统,其中最知名最好用的就是DTL和Jinja2。 DTL 是 Django Template Language 三个单词的缩写,也就是Django自带的模板语言。当然也可以配置Django支持Jinja2等其他模板引擎,但是作为Django内置的模板语言,和Django可以达到无缝衔接而不会产生一些不兼容的情况。因此建议大家学习好DTL。
现在总结下概念,为后面的学习做准备:

DTL(Django Template Language )名叫Django模板语言,用DTL编写的是一个DTL模板文件,这个文件是一个带有特殊语法的HTML文件,利用pycharm创建一个Django项目,那么会自动生成一个template文件夹,这个文件夹就是存放项目的DTL模板文件(也就是带有特殊语法的HTML文件)。在视图函数里面可以利用render_to_string方法将指定的DTL模板文件编译后渲染成Python的字符串格式,然后用HttpResponse方法打包返回给客户端,或者在视图函数里面直接利用render方法将指定的DTL模板文件渲染接着自动打包成HttpResponse,然后视图函数返回给客户端。

渲染模板

渲染模板有多种方式。这里讲下两种常用的方式。
(1) render_to_string:该函数会自动在templates文件夹搜寻DTL模板文件,找到后接着将DTL模板文件编译后渲染成Python的字符串格式。最后再通过HttpResponse类包装成一个HttpResponse 对象返回回去。
1.修改views.py代码如下:

from django.template.loader import render_to_string
from django.http import HttpResponse

def index(request):
    html = render_to_string("index.html")  # 该函数在templates文件夹搜寻是否含有index.html文件,找到后将该文件(DTL模板文件)编译后渲染成Python的字符串格式
    return HttpResponse(html)  # 然后将html通过HttpResponse包装后返回给浏览器进行显示

2.templates文件夹就是专门存放DTL模板文件的,在工程目录中可以找到这个文件夹。然后在templates文件夹下添加index.html文件,如下图所示:
谈谈Python之Django搭建企业级官网(第四篇上)
3.添加index.html后,默认会生成一些html5的代码,接着我们修改该文件,在浏览器中显示一段文字:
谈谈Python之Django搭建企业级官网(第四篇上)
4.运行Django项目,然后输入127.0.0.1:8000,显示结果如下(成功访问到了我们渲染的模板文件index.html):
谈谈Python之Django搭建企业级官网(第四篇上)
(2)以上方式虽然已经很方便了。但是django还提供了一个更加简便的方式-render方法(推荐该方式),直接将模板渲染成字符串和包装成 HttpResponse 对象一步到位完成。
1.在前一个测试render_to_string方法的代码基础上,修改views.py文件代码如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, "index.html")  # render方法很方便,只要第一个参数指定request对象,第二个参数指定模板文件的路径,然后它会自动在templates文件夹下搜寻该文件,然后自动渲染再用HttpResponse包装返回。

按下Ctrl+S保存,输入127.0.0.1:8000,显示结果如下(再次成功访问到了我们渲染的模板文件index.html):
谈谈Python之Django搭建企业级官网(第四篇上)
2.分析render函数的内部实现,源代码如下图:
谈谈Python之Django搭建企业级官网(第四篇上)
从上图可以看出,其实render方法内部也是调用render_to_string渲染、HttpResponse包装再返回,直接使用render方法减轻了我们对代码的编写,并且让代码更美观简洁,嗯~的确不错。

模板查找路径配置

上一小节我介绍了如何渲染模板,其中render或render_to_string方法有一个参数是指定DTL模板文件,然后在templates文件夹下查找指定的DTL模板文件。其实,对于DTL模板文件有一个专门的查找路径,容许我一一道来。在项目的 settings.py 文件中。有一个 TEMPLATES 配置,这个配置包含了模板引擎的配置,模板查找路径的配置等。如下图所示:
谈谈Python之Django搭建企业级官网(第四篇上)
这个TEMPLATES配置里面有两个重要的属性:DIRS、APP_DIRS。DTL模板文件查找路径可以通过这两个属性配置。
(1) DIRS :这是一个列表,在这个列表中可以存放所有的DTL模板文件路径,以后在视图中使用 render 或者 render_to_string 渲染模板的时候,会在这个列表的路径中查找模板。一般情况下是“os.path.join(BASE_DIR, 'templates')”,os.path.join()函数是将BASE_DIR和‘templates’拼接,其中BASE_DIR是当前项目的路径,注意,不论项目被移动到哪个目录下,BASE_DIR都会动态修改当前项目的路径,怎么实现动态?一样定位到settings.py文件前面的代码,如下图:
谈谈Python之Django搭建企业级官网(第四篇上)
意思是说无论将项目放到哪里,利用render等函数渲染模板时,都可以找到templates目录下的DTL模板文件,因为BASE_DIR和‘templates’拼接起来其实就是templates文件夹的绝对路径。
(2)APP_DIRS :默认为 True ,这个设置为 True 后,如果在DIRS指定的模板查找路径不能找到模板文件,那么就会在 INSTALLED_APPS 安装了的APP下的 templates 文件加中查找模板。一样定位到settings.py文件前面的代码,如下图(默认安装了一些Django项目必须的app):
谈谈Python之Django搭建企业级官网(第四篇上)
这个APP_DIRS的作用是当DIRS不能找到模板文件时,就在其他app上查找模板,需要进行以下两步:1.在INSTALLED_APPS添加app的名字。例如:"front"。2.在app目录下创建一个名为templates的文件夹(必须是这个名字,其他不允许),然后添加DTL模板文件。那么当DIRS找不到时就跑这个app里的templates目录找模板。

模板查找路径小总结

DTL模板文件查找顺序:比如代码 render('list.html') 。先会在 DIRS 这个列表中依次查找路径下有没有这个模板,如果有,就返回。如果 DIRS 列表中所有的路径都没有找到,那么会先检查当前这个视图所处的 app (什么叫当前这个视图所在的app?其实就是假如views.py在front这个app目录下,那么front就是当前这个视图所处的app。) 是否已经安装,如果已经安装了,那么就先在当前这个 app 下的 templates 文件夹中查找模板,如果没有找到,那么会在其他已经安装了的 app 中查找。如果所有路径下都没有找到,那么会抛出一个 TemplateDoesNotExist 的异常。

DTL模板语法

变量

模板中可以包含变量, Django 在渲染模板的时候,可以传递变量对应的值过去进行替换。变量的命名规范和 Python 非常类似,只能是阿拉伯数字和英文字符以及下划线的组合,不能出现标点符号等特殊字符。变量需要通过视图函数渲染,视图函数在使用 render 或者 render_to_string 的时候可以传递一个 context 的参数,这个参数是一个字典类型。以后在模板中的变量利用{{变量名}}从这个字典中读取值的。
举个变量的栗子:
(1)修改views.py代码如下(添加context参数来为DTL模板文件传递变量):

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "username": "CFishHome学习"
    }
    return render(request, "index.html", context=context)  # 函数指定关键字参数context来传递变量

(2)修改index.html模板的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
    {{ username }}  
</body>
</html>

按下Ctrl+S保存,注意要在python文件保存,在index.html下保存不能自动重新运行。运行结果如下:
谈谈Python之Django搭建企业级官网(第四篇上)

各种变量类型的解析

事实上,context字典键一般为变量名(字符串类型),而值有多种类型,其中包括前面列举的字符串、字典、元组、列表、类对象、函数名等。下面一一举例测试常用的几种变量类型的使用,字符串类型前面已列举,这里不再演示:
(1)字典
与Python语法不同的是,DTL语法不允许通过中括号的形式访问字典或列表中的值,比如dict['key']和list[1]是不支持的!不要问为什么,规则是那些大牛们定下来的,我们只能遵循他们定下的规则。
修改views.py代码如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": {
            "book_id": "A001",
            "book_name":"人民的名义",
            "book_price":1000
        }
    }
    return render(request, "index.html", context=context)

修改index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.book_id }}</p>
<p>{{ book.book_name }}</p>
<p>{{ book.book_price }}</p>
</body>
</html>

按下Ctrl+S保存,运行结果如下(成功访问字典的键所对应的值):
谈谈Python之Django搭建企业级官网(第四篇上)
因为字典可以使用点(.)语法获取字典键所对应的值,并且也可以使用点(.)语法调用字典内置的方法,所以在给这个字典添加key的时候,千万不能和字典中的一些属性或方法重复。比如items,items是字典的方法,那么如果给这个字典添加一个items作为key,那么以后就不能再通过item来访问这个字典的键值对了,而是变成访问我们自定义的items键所对应的自定义的值了。下面举个栗子:
1.通过{{ 变量名.函数名 }}就可以调用该变量对应的函数了,修改index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.book_id }}</p>
<p>{{ book.book_name }}</p>
<p>{{ book.book_price }}</p>
<p>{{ book.keys }}</p>
</body>
</html>

运行结果如下,通过字典内置的keys方法,成功访问到了该字典含有的所有键:
谈谈Python之Django搭建企业级官网(第四篇上)
2.修改views.py文件的context内容,添加与字典内置函数Keys冲突的keys键和对应的值,代码如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": {
            "book_id": "A001",
            "book_name": "人民的名义",
            "book_price": 1000,
            "keys": 200
        }
    }
    return render(request, "index.html", context=context)

按下Ctrl+S保存,运行结果如下:
谈谈Python之Django搭建企业级官网(第四篇上)
从上图可以看出,我们自定义的与字典内置函数keys冲突的keys键被解析显示在页面上,但是字典内置函数keys永远都执行不到了,因为被覆盖了。所以在此提个建议:给字典添加key的时候,千万不能和字典中的一些属性或方法重复,不然会被覆盖。
(2)列表或者元组
如果book是一个列表或者元组,是不能通过中括号的形式访问列表和元组中的值,比如list[1]是不支持的!只能够通过'.'来访问。
1.修改views.py文件的context内容,代码如下:

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    context = {
        "book": ["水浒传", "人民的名义", "鲁迅自传", "钢铁是怎样炼成的"],
        "price": (100, 200, 300, 400)
    }
    return render(request, "index.html", context=context)

2.通过{{ 变量名.下表 }}就可以访问该变量对应的元素值了,修改index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.0 }}</p>
<p>{{ book.1 }}</p>
<p>{{ book.2 }}</p>
<p>{{ book.3 }}</p>
<p>{{ price.0 }}</p>
<p>{{ price.1 }}</p>
<p>{{ price.2 }}</p>
<p>{{ price.3 }}</p>
</body>
</html>

按下Ctrl+S保存,运行结果如下:
谈谈Python之Django搭建企业级官网(第四篇上)
(3)类对象
如果book是一个对象,那么就会可以在模板访问这个对象的属性,或者是方法。
1.修改views.py文件的context内容,代码如下:

from django.shortcuts import render
from django.http import HttpResponse

class A:
    def __init__(self, count):
        self.count=count

    def show(self):
        print("我是一个类")

def index(request):
    a = A(100)
    context = {
        "book": a
    }
    return render(request, "index.html", context=context)

2.通过{{ 变量名.属性或者函数名 }}就可以访问该对象对应的属性或调用对应的函数了,修改index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.show }}</p>
<p>{{ book.count }}</p>
</body>
</html>

按下Ctrl+S保存,运行结果如下:
谈谈Python之Django搭建企业级官网(第四篇上)
由上可得出,在DTL模板文件成功访问到对象的属性,第一个输出的是None,因为只是单纯的调用(输出信息在下图所示控制台)。
谈谈Python之Django搭建企业级官网(第四篇上)
(4)函数
book也可以是一个函数名(例如:show或show()),代表这个函数,在DTL模板文件中引用时也是{{ 变量名 }}方式调用函数,需要注意的是这种方式是无法传递函数参数的,所以这个函数在定义时写参数也没用。
1.修改views.py文件的context内容,代码如下:

from django.shortcuts import render
from django.http import HttpResponse

def show():
    print("我是一个简单的函数")

def index(request):
    context = {
        "book": show
    }
    return render(request, "index.html", context=context)

2.通过{{ 变量名.函数名 }}就可以访问该函数了,修改index.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CFishHome</title>
</head>
<body>
<p>{{ book.show }}</p>
</body>
</html>

按下Ctrl+S保存,运行结果如下:
谈谈Python之Django搭建企业级官网(第四篇上)

Django测试项目8000端口被酷狗占用问题

创建了一个Django项目,但是运行时报错可能会报下面这个错误:
谈谈Python之Django搭建企业级官网(第四篇上)
为什么会报这个错误?其实就是端口被占用了,那以我目前这个电脑程序运行情况举例,我开机->打开酷狗(听音乐)->打开pycharm->创建Django项目(默认使用8000端口)->运行项目->报端口占用错误。
我们打开CMD执行以下命令:
谈谈Python之Django搭建企业级官网(第四篇上)
第一条命令找出8000端口对应的PID进程为2032,第二条命令通过进程ID找出进程对应的详细信息,可以看到这个进程对应的是酷狗服务。问题找到了,就是因为我们先开启了酷狗,酷狗服务占用了我们的测试端口。所以解决办法有两个:

1.关闭酷狗再重新运行Django项目。

2.将Django项目的测试端口改为其他,例如:9000

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!