[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

时间:2023-01-24 17:44:14

一、实现一个简单的Web服务器

使用Python标准库提供的独立WSGI服务器来实现MVC架构。

首先,实现一个简单的Web服务器:

from wsgiref.simple_server import make_server

# 每当一个请求连接,这个函数被调用一次
def RunServer(environ, start_response):
# 返回响应头、状态等
start_response('200 OK', [('Content-Type', 'text/html')])
# 返回响应体数据
return ['<h1>Hello World</h1>'.encode('utf-8'), ] def main():
# 创建一个服务器,监听端口为8000,绑定运行函数为RunServer()
httpd = make_server('', 8000, RunServer)
print('Servering HTTP in port 8000..')
# 无线循环
httpd.serve_forever() if __name__ == '__main__':
main()

添加处理URL的功能:

from wsgiref.simple_server import make_server
import time # 对应'/index'的处理函数
def handle_index():
return ["<h1>Index Page...</h1>".encode('utf-8'), ] # 对应'/register'的处理函数
def handle_register():
return ["<h1>Register Page...</h1>".encode('utf-8'), ] # 对应'/date'的处理函数
def handle_date():
return [("<h1>Date:" + str(time.time()) + "</h1>").encode('utf-8'), ] # 全局字典,手工添加映射关系
URL_DICT = {
'/index': handle_index,
'/register': handle_register,
'/date': handle_date
} # 每当一个请求连接,这个函数被调用一次
def RunServer(environ, start_response):
# 返回响应头、状态等
start_response('200 OK', [('Content-Type', 'text/html')]) # 检查字典中是否存在映射关系,如果有则调用对应的函数,如果没有则返回404
current_url = environ['PATH_INFO']
func = None
if current_url in URL_DICT:
func = URL_DICT[current_url]
if func:
return func()
else:
return ['<h1>404 Error Page..</h1>'.encode('utf-8'), ] def main():
# 创建一个服务器,监听端口为8000,绑定运行函数为RunServer()
httpd = make_server('', 8000, RunServer)
print('Servering HTTP in port 8000..')
# 无线循环
httpd.serve_forever() if __name__ == '__main__':
main()

上述代码添加了处理URL的功能,可以根据不同的URL返回不同的数据。

主要的关键点:

1.使用一个全局的字典来存放URL和处理函数之间的映射关系(注意,这里的映射关系是写死的,也就是说我们要添加一个页面,就得手工往字典中添加一个映射关系)

2.每个URL使用一个独立的函数进行处理

我们可以通过处理函数读取index.html文件中的内容,然后将其返回

对handle_index()进行修改:

# 对应'/index'的处理函数
def handle_index():
data = b''
with open('index.html', 'rb') as f:
data = f.read()
return [data, ]

添加一个index.html文件:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Index Page</title>
</head>
<body>
<h1>This is @user Index Page...</h1>
</body>
</html>

这里的@user可以用数据库读取的内容来替换。

二、MVC架构

我们参考第一节中的代码,将其修改为MVC架构。

修改项目的目录结构,添加View、Controller和Model三个目录:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

Controller:用于存放业务处理逻辑代码,例如前面的handle_index()等。功能例如读取Html文件,替换数据,返回数据等。

Model:用于存放数据库操作等代码。这些代码用于读取数据库数据,并将数据返回给Controller。

View:用于存放前端页面文件,例如Html等。主要是Html模板。

我们将index.html这类静态文件放入View目录中。

将handle处理函数全部分离到handler.py中,然后放到Controller中:

import time
from Model import read_db # 对应'/index'的处理函数
def handle_index():
data = b''
with open('Template/index.html', 'rb') as f:
data = f.read() user = read_db.get_user()
print(user)
   # 将index.html中的@user替换为从数据库中获取的数据,这里例如"Leo"
data = data.replace(b"@user", user.encode('utf-8'))
return [data, ] # 对应'/register'的处理函数
def handle_register():
return ["<h1>Register Page...</h1>".encode('utf-8'), ] # 对应'/date'的处理函数
def handle_date():
return [("<h1>Date:" + str(time.time()) + "</h1>").encode('utf-8'), ]

这样,将所有的文件分类放置。将整个项目划分为MVC三个层面,叫做MVC架构

三、MTV架构

对应MVC架构,还有一种叫做MTV架构,实际上他们是一样的:

架构名称 数据库处理 模板文件 业务处理
MVC Model View Controller
MTV Model Template View

如上表所示,MVC和MTV架构只是名字的对应关系不一样。

在MTV中,html文件属于Template,而业务处理叫做View。

通过修改项目目录结构,将MVC修改为MTV结构:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

四、安装Django

使用PYTHON_HOME/Scripts/pip.exe来安装Django:

# 使用清华源安装django
pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple

将PYTHON_HOME/Scripts添加到环境变量:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

使用django-admin命令来创建一个django项目:

D:\>django-admin startproject firstsite

其中firstsite是django项目名称,我们在D盘根目录下执行命令,项目则存在于这个目录下。

进入生成的firstsite目录,我们可以看到:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

使用manage.py运行django程序:

D:\firstsite>python manage.py runserver 127.0.0.1:
Watching for file changes with StatReloader
Performing system checks... System check identified no issues ( silenced). You have unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December , - ::
Django version 3.0, using settings 'firstsite.settings'
Starting development server at http://127.0.0.1:8001/
Quit the server with CTRL-BREAK.

访问127.0.0.1:8001,可以看到以下页面,表示django运行成功:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

除了使用django-admin命令创建django程序,还可以直接在Pycharm中创建:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

Pycharm会创建一个一样的django程序:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

点击Pycharm右上角的运行按钮即可运行django:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

注意,这里一定要选择项目名运行,否则运行报错。如果要修改运行的host和port,则进入Edit Configurations中进行修改。

You have  unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December , - ::
Django version 3.0, using settings 'secondsite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

五、django目录介绍

1.用Pycharm打开已经创建好的django程序

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

2.django程序目录结构

firstsite
-- firstsite # 对整个程序进行配置的目录
-- __init__
-- settings.py # 配置文件
-- urls.py # URL对应关系
-- wsgi.py # 遵循WSGI规范,默认使用的是wsgiref,上线的话要使用uwsgi + nginx
-- db.sqlite3
-- manage.py # 管理Django程序,例如创建一个APP:python manage.py startapp xxx
django的ORM:python manage.py makemigrations
python manage.py migrate

六、django中的APP

1.APP概念

我们创建一个django工程以后,我们可以创建多个APP,每个APP代表着一个子模块,如图:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

这个运维平台看做一个django project,而下面的 资产、配管、私有云等都是一个APP。

2.创建一个APP

在Pycharm中使用命令行来创建(Pycharm最下方可以选择Terminal页签):

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

执行命令:

d:\Dev_apps\Anaconda5.3.0\python.exe manage.py startapp cmdb

其中,cmdb是APP名称。

当然,我们也可以使用windows cmd命令窗口执行。

创建完毕后,我们可以看到生成了一个cmdb目录:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

3.测试使用APP

在cmdb APP中,我们找到Views文件:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

然后在其中添加请求处理函数:

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse # /cmdb.html请求的处理函数
def cmdb_home(request):
return HttpResponse("<h1>CMDB home page..</h1>")

在secondsite/urls.py中添加一条映射关系:

from cmdb import views

urlpatterns = [
path('admin/', admin.site.urls),
path('cmdb.html/', views.cmdb_home),
]

运行django程序,访问页面:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

七、APP的目录结构

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

1.miragtions目录:

在 [Python自学] day-12 (Mysql、事务、索引、ORM) 中,我们使用过ORM框架 SQLAlchemy。

在SQLAlchemy中,我们可以创建表、增删改查数据等,但无法对表结构进行修改

但在django框架中,他所提供的ORM功能非常厉害,可以提供很细致化的操作,例如删除表的列、修改列的数据类型、数据长度等等。

我们在某个Django APP目录中可以看到一个叫做migrations的目录

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

这个目录是用来记录数据库操作的,当我们做了修改表结构等数据库操作后,django会自动在migrations目录中生成记录,我们无法人工干预。

2. admin.py

该目录是django为我们提供的数据库后台管理,可以用很少的代码实现一个功能比较完整的后台管理页面。效果如下:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

默认情况下,django为我们提供了一个轻量级数据库Sqlite3:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

3.apps.py

用于配置当前APP

4.models.py

就是django给我们提供的ORM,我们在里面写指定的类,然后通过manage.py makemigrations和manage.py migrate就可以创建表和修改表结构(会在migrations目录中产生记录文件)。

5.tests.py

单元测试

6.views.py

业务逻辑代码

八、实现简单的login页面

在cmdb APP中实现简单的Login页面。

1.在urls.py中添加相应的映射关系

from cmdb import views

urlpatterns = [
path('admin/', admin.site.urls),
path('login/', views.login),
]

2.在工程的根目录下创建一个目录叫templates

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

3.在templates目录下创建login.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<style>
label{
width: 80px;
text-align: right;
display: inline-block;
}
</style>
</head>
<body>
<form action="/login" method="post">
<p>
<label for="username">用户名:</label>
<input id="username" type="text" />
</p>
<p>
<label for="password">密码:</label>
<input id="password" type="password"/>
<input type="submit" value="提交"/>
</p>
</form>
</body>
</html>

4.在cmdb/views.py中写业务逻辑代码

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse def login(request):
f = open("templates/login.html", 'r', encoding="utf-8")
data = f.read()
return HttpResponse(data)

在业务代码中,我们使用open()打开html文件,读取内容并返回给客户端。

但是如果我们有很多页面,则每个都要手工打开文件读取。Django为我们提供了相应的处理方法。

5.使用render来打开html模板

修改views.py中的业务逻辑代码:

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render def login(request):
return HttpResponse(render(request, 'login.html'))

从django.shortcuts中导入render,然后使用render来读取templates/login.html文件。

注意:这里我们没有使用templates/login.html路径,而是直接使用login.html。render()方法之所以能直接找到login.html文件,是因为在setting.py文件中对模板路径的默认配置就是templates。如下:

# setting.py文件

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

配置文件中的BASE_DIR就是django工程的根目录(这里是secondsite)。这里将BASE_DIR和'templates'拼接在一起作为模板的DIR。

6.访问/login

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

九、静态文件处理

当我们要在项目中添加静态文件是,例如css、js、图片等。

1.在项目根目录下创建目录static

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

2.将需要的静态文件拷贝到static目录中

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

其中commons.css内容如下:

.common{
background-color: #eeeeee;
}

3.在login.html中使用css文件和jQuery

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="/static/commons.css"/>
<style>
label{
width: 80px;
text-align: right;
display: inline-block;
}
</style>
</head>
<body class="common">
<form action="/login" method="post">
<p>
<label for="username">用户名:</label>
<input id="username" type="text" />
</p>
<p>
<label for="password">密码:</label>
<input id="password" type="password"/>
<input type="submit" value="提交"/>
</p>
</form>
<script src="/static/jquery-1.12.4.js"></script>
</body>
</html>

4.访问/login报错404

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

当页面在请求/static/commons.css和/static/jquery-1.12.4.js时报404错误,说明资源为找到。

有两种解决方法:

1) 在urls中添加映射关系(可以实现,但不能这么做,静态文件django可以专门处理)

2) 在setting中配置静态文件的路径(正解)

5.在settings中配置静态文件路径

在settings.py配置文件的最后添加以下代码:

STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'), # 这里必须有逗号
)

6.再次访问/login

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

页面访问正常,并且background-color已经变为灰色(commons.css中指定的)。

7.填写表单并提交报错

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

这是因为我们的表单提交的目的地是/login。

解决方法一:urls.py中的匹配字符串为"login/",所以表单提交地址应该修改为action="/login/"

解决方法二:urls.py中修改为"login"action="/login"

这样对应起来,才能匹配。

8.再次提交报错

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

这是CSRF(跨站点请求伪造)错误。参照下一节django配置,将CSRF相关配置注释。

十、Django配置

以上章节中已经描述了django的两项配置:

1)对templates路径的配置

2)对static路径的配置

1.对CSRF进行配置:

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

在settings.py中将csrf相关的配置项注释掉。

2.配置Django时区:

如果不进行时间配置,Django默认时间比上海时间延后8小时。

在setting中配置时间:

# 将时区修改为上海
# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai' #将USE_TZ修改为false
# USE_TZ = True
USE_TZ = False

十一、获取请求参数

在我们实现的请求处理业务逻辑代码中,我们可以获取来自客户端请求的所有参数:

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render def login(request):
return HttpResponse(render(request, 'login.html'))

这些请求参数,都通过 client-->Webserver-->wsgi-->django 将其作为函数参数传递到被调用的login()函数中。

我们通过request就可以获取到客户端的所有参数

1.通过参数判断请求类型

# cmdb views.py

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render def login(request):
if request.method == 'POST':
print("Post")
elif request.method == 'GET':
print('Get')
return HttpResponse(render(request, 'login.html'))

当我们第一次访问/login时,后台会打印"GET",当我们提交表单是,后台会打印"POST"。

2.获取POST提交的数据

POST提交的数据是以字典形式组织的,所以,首先要在html表单中为<input>标签指定name属性作为key。

<body class="common">
<form action="/login/" method="post">
<p>
<label for="username">用户名:</label>
<input id="username" type="text" name="user"/>
</p>
<p>
<label for="password">密码:</label>
<input id="password" type="password" name="pwd"/>
<input type="submit" value="提交"/>
</p>
</form>
<script src="/static/jquery-1.12.4.js"></script>
</body>

然后在后台通过request获取POST数据:

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render def login(request):
if request.method == 'POST':
# username = request.POST['user'] # 尽量不要用这种方式,因为user如果不存在,则会报错
username = request.POST.get('user', None)
password = request.POST.get('pwd', None)
print("username : %s\npassword : %s" % (username, password))
elif request.method == 'GET':
print('Get')
return HttpResponse(render(request, 'login.html'))

3.验证数据并跳转

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect def login(request):
if request.method == 'POST':
username = request.POST.get('user', None)
password = request.POST.get('pwd', None)
# 验证user和pwd,如果正确,则跳转到www.baidu.com
if username == 'leokale' and password == '':
return redirect('http://www.baidu.com')
elif request.method == 'GET':
print('Get')
return HttpResponse(render(request, 'login.html'))

这里的跳转要使用return redirect("http://www.baidu.com")

4.提交错误数据,返回错误消息

以下代码实现了错误消息提示,但页面会刷新(实际上是返回了一个新的页面,包含了错误信息),以后可以使用Ajax异步请求来实现错误提示。

1)在html中,添加错误信息的标签

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
<link rel="stylesheet" href="/static/commons.css"/>
<style>
label{
width: 80px;
text-align: right;
display: inline-block;
}
.error_span{
color: red;
}
</style>
</head>
<body class="common">
<form action="/login/" method="post">
<p>
<label for="username">用户名:</label>
<input id="username" type="text" name="user"/>
<span class="error_span">{{ user_error }}</span>
</p>
<p>
<label for="password">密码:</label>
<input id="password" type="password" name="pwd"/>
<input type="submit" value="提交"/>
<span class="error_span">{{ pwd_error }}</span>
</p>
</form>
<script src="/static/jquery-1.12.4.js"></script>
</body>
</html>

2)验证user和pwd错误时,django自动替换错误信息

from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
from django.shortcuts import render
from django.shortcuts import redirect def login(request):
if request.method == 'POST':
username = request.POST.get('user', None)
password = request.POST.get('pwd', None)
# 验证user和pwd,如果正确,则跳转到www.baidu.com
if username == 'leokale' and password == '':
return redirect('http://www.baidu.com') user_error_msg = ''
pwd_error_msg = ''
if username != 'leokale':
user_error_msg = "账号不存在"
if password != '':
pwd_error_msg = "密码不正确"
# 当user或pwd错误时,django自动使用第三个参数字典中的数据对html中的{{ xxx }}进行替换
return HttpResponse(render(request, 'login.html', {"user_error": user_error_msg, "pwd_error": pwd_error_msg})) elif request.method == 'GET':
print('Get')
return HttpResponse(render(request, 'login.html'))

访问/login,提交错误的数据,效果如下:

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

十二、实现简单后台管理功能(利用Django模板语言)

请求后台管理页面:http://127.0.0.1/home

1.在urls.py中添加映射关系

from cmdb import views

urlpatterns = [
path('admin/', admin.site.urls),
path('login', views.login),
path('home', views.home), # 后台管理页面映射,映射到cmdb.views.home方法
]

2.home.html页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body style="margin: 0">
<div style="height: 48px;background-color: #dddddd"></div>
<div>
<!-- 如果用户点击添加按钮,则使用post提交表单 -->
<form action="/home" method="post">
<input type="text" name="username"/>
<input type="text" name="email"/>
<input type="text" name="gender"/>
<input type="submit" value="添加"/>
</form>
</div>
<div>
<!-- 在table中使用模板语言进行循环,获取user_list中的数据(来自后台render函数的第三个参数) -->
<table>
{% for row in user_list %}
<tr>
<td>{{ row.username }}</td>
<td>{{ row.email }}</td>
<td>{{ row.gender }}</td>
</tr>
{% endfor %}
</table>
</div>
</body>
</html>

在前台html代码中,<table>标签中的数据是动态生成的(来自后台读取全局列表的数据,模拟数据库操作),所以在render返回home.html页面数据时要对<table>的内容进行替换。

这里使用模板语言,{% %}中使用循环语句{{ }}中进行取值

3.在cmdb APP的views.py中写请求处理函数

# 全部列表,用于用户数据(模拟数据库)
USER_LIST = [
{'username': 'Alex', 'email': 'alex@163.com', 'gender': 'Male'},
] # 后台管理页面
def home(request):
# 如果是post请求,说明是用户点击添加按钮提交了表单
if request.method == 'POST':
# 获取表单中的值,然后添加到列表中(模拟数据库)
user = request.POST.get('username', None)
email = request.POST.get('email', None)
gender = request.POST.get('gender', None)
content = {'username': user, 'email': email, 'gender': gender}
USER_LIST.append(content)
# 返回home页面信息
return render(request, 'home.html', {'user_list': USER_LIST})

当请求是POST类型时,说明用户提交了新的用户数据,使用request获取数据,并存放到列表(模拟数据库)中。然后将列表中的全部数据作为参数交给django框架,框架对home.html进行替换后返回给浏览器。

十三、Django框架中请求的生命周期

[Python自学] day-18 (2) (MTV架构、Django框架、模板语言)

一个非静态资源请求的URL,生命周期一般如上图所示:

1.客户端发送请求给服务器(图中省略),服务器将请求交给django的路由系统(对应urls.py)

2.路由系统判断是否存在对应的映射,如果存在,则找到并执行对应的视图方法(对应APP中的views.py中的函数或类)

3.视图方法根据业务需求,从数据库等存储中获取业务数据,并使用指定的模板文件(对应html文件)来渲染显示效果(即使用业务数据替换html中指定部分)

4.返回合并好的数据给客户端(浏览器)

十四、Django基础内容总结

1.创建Django工程:

使用命令行:django-admin startproject pro_name

或者使用pycharm创建

2.创建APP

使用命令行:python manage.py startapp app_name

3.配置Django

配置静态文件目录:settings.py

最后添加:

STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)

配置模板文件目录(默认是templates):settings.py

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

禁用CSRF认证(防止post提交403错误):settings.py

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

4.定义路由规则

在urls.py中添加访问URL于视图函数之间的映射关系

  例如:"login" ---> func_name

5.定义视图函数

在app的views.py中定义视图函数

def func_name(request):
if request.method == 'POST':
data = request.POST.get('data_name', None)
pass
elif request.method == 'GET':
data = request.GET.get('data_name', None)
pass
return render(request, 'xxx.html', {'data_key': data_value})

返回字符串:

return HttpResponse("字符串")

返回模板:

return render(request,'xxx.html',{替换数据字典})

重定向:

return redirect('/login')  # 这里的"/"表示本地,即httP://127.0.0.1/
return redirect('http://www.baidu.com') # 外部url

十五、模板渲染(模板语言)

在Django中存在一套特殊的模板语言:

在settings.py中可以看到:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Django提供的默认模板语言叫做DjangoTemplates,这套模板语言可能存在一些局限性,我们可以将其修改为Jinjia2模板语言:

'BACKEND': 'django.template.backends.jinja2.Jinja2',

但是在这里,我们还是先学习默认的模板语言*(^。^)**。以下都是默认模板语言,Jinjia2以后再学习。

在使用render返回数据时,Django会将数据和模板合并

return render(request, 'index.html', {'current_user': 'Leo',
'user_list': ['Alex', 'Eric', 'Jone', 'Leo'],
'user_dict': {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'},
'age': 18
})

在index.html中使用{{ username }}就可以获取到user的值,并自动替换在相应的位置:

<div>{{ username }}</div>

替换后变为:

<div>Leo</div>

index.html中使用循环获取user_list中的值:

    <ul>
{% for row in user_list %}
<li>{{ row }}</li>
{% endfor %}
</ul>

获取列表中的某个值:

<div>{{ user_list.2 }}</div>  <!-- 获取user_list中的第2个值 -->
<div>{{ user_list.3 }}</div> <!-- 获取user_list中的第3个值 -->

index.html中循环获取user_dict中的值:

<!-- 获取所有key -->
<ul>
{% for row in user_dict.keys %}
<li>{{ row }}</li>
{% endfor %}
</ul>
<!-- 获取所有value -->
<ul>
{% for row in user_dict.values %}
<li>{{ row }}</li>
{% endfor %}
</ul>
<!-- 获取所有key和value -->
<ul>
{% for key,value in user_dict.items %}
<li>{{ key }} <---> {{ value }}</li>
{% endfor %}
</ul>

通过key获取字典中的值:

<div>{{ user_dict.k1 }}</div>  <!-- 获取字典中键为k1对应的值-->
<div>{{ user_dict.k2 }}</div> <!-- 获取字典中键为k2对应的值-->

循环计数:

如果想在循环中打印循环的次数(count),可以使用以下方式:

<ul>
{% for row in user_list %}
<li>{{ forloop.counter }}</li> <!-- 从1开始计数 -->
<li>{{ forloop.counter0 }}</li> <!-- 从0开始计数 -->
<li>{{ forloop.revcounter }}</li> <!-- 1开始计数,但是反向排列 -->
<li>{{ forloop.revcounter0 }}</li> <!-- 0开始计数,但是反向排列 -->
<li>{{ forloop.first }}</li> <!-- 第一次循环为True,后面全为False -->
<li>{{ forloop.last }}</li> <!-- 第一次循环为False,后面全为True -->
{% endfor %}
</ul>

如果是多层循环:

<ul>
{% for outer in user_list %}
{% for row in user_list %}
<li>{{ forloop.parentloop }}</li> <!-- 外层循环的6个属性,以字组织 -->
<li>{{ forloop.parentloop.counter }}</li> <!-- 获取外层循环的次数(1开始计数) -->
{% endfor %}
{% endfor %}
</ul>

if判断语句:

{% if age %}
<a>有年龄信息</a>
{% if age > 16 %}
<a>老男人</a>
{% else %}
<a>小鲜肉</a>
{% endif %}
{% else %}
<a>没有年龄信息</a>
{% endif %}