一、实现一个简单的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三个目录:
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结构:
四、安装Django
使用PYTHON_HOME/Scripts/pip.exe来安装Django:
# 使用清华源安装django
pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple
将PYTHON_HOME/Scripts添加到环境变量:
使用django-admin命令来创建一个django项目:
D:\>django-admin startproject firstsite
其中firstsite是django项目名称,我们在D盘根目录下执行命令,项目则存在于这个目录下。
进入生成的firstsite目录,我们可以看到:
使用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运行成功:
除了使用django-admin命令创建django程序,还可以直接在Pycharm中创建:
Pycharm会创建一个一样的django程序:
点击Pycharm右上角的运行按钮即可运行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程序
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代表着一个子模块,如图:
这个运维平台看做一个django project,而下面的 资产、配管、私有云等都是一个APP。
2.创建一个APP
在Pycharm中使用命令行来创建(Pycharm最下方可以选择Terminal页签):
执行命令:
d:\Dev_apps\Anaconda5.3.0\python.exe manage.py startapp cmdb
其中,cmdb是APP名称。
当然,我们也可以使用windows cmd命令窗口执行。
创建完毕后,我们可以看到生成了一个cmdb目录:
3.测试使用APP
在cmdb APP中,我们找到Views文件:
然后在其中添加请求处理函数:
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程序,访问页面:
七、APP的目录结构
1.miragtions目录:
在 [Python自学] day-12 (Mysql、事务、索引、ORM) 中,我们使用过ORM框架 SQLAlchemy。
在SQLAlchemy中,我们可以创建表、增删改查数据等,但无法对表结构进行修改。
但在django框架中,他所提供的ORM功能非常厉害,可以提供很细致化的操作,例如删除表的列、修改列的数据类型、数据长度等等。
我们在某个Django APP目录中可以看到一个叫做migrations的目录:
这个目录是用来记录数据库操作的,当我们做了修改表结构等数据库操作后,django会自动在migrations目录中生成记录,我们无法人工干预。
2. admin.py
该目录是django为我们提供的数据库后台管理,可以用很少的代码实现一个功能比较完整的后台管理页面。效果如下:
默认情况下,django为我们提供了一个轻量级数据库Sqlite3:
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
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
九、静态文件处理
当我们要在项目中添加静态文件是,例如css、js、图片等。
1.在项目根目录下创建目录static
2.将需要的静态文件拷贝到static目录中
其中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
当页面在请求/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
页面访问正常,并且background-color已经变为灰色(commons.css中指定的)。
7.填写表单并提交报错
这是因为我们的表单提交的目的地是/login。
解决方法一:urls.py中的匹配字符串为"login/",所以表单提交地址应该修改为action="/login/"。
解决方法二:urls.py中修改为"login",action="/login"。
这样对应起来,才能匹配。
8.再次提交报错
这是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,提交错误的数据,效果如下:
十二、实现简单后台管理功能(利用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框架中请求的生命周期
一个非静态资源请求的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 %}