Django后端框架
安装Django
2005 年发布,采用Python语言编写的开源web框架。
早期的时候Django主做新闻和内容管理。
重量级的Python Web框架,Django配备了常用的大部分组件。
yum install -y python39
pip3 install django == 4.0 .10
pip3 list | grep -i django
https://www.djangoproject.com/download/
官网下载离线安装包Django-4.0.10.tar.gz
yum remove -y python3
yum install -y python39
tar xf Django-4.0.10.tar.gz
cd Django-4.0.10
python3 setup.py install
pip3 list | grep -i django
创建项目、启动服务
1 . 安装Django
2 . ` django-admin startproject 项目名` ,创建项目目录,内含同名子目录和脚本manage.py
3 . ` python3 项目名/manage.py runserver [ 端口] ` ,前台启动服务
4 . 关闭服务的两种方式:
方式一:在启动服务的终端使用 Ctrl+C 终止服务。
方式二:在第二终端杀死服务的进程。
ss -nutlp | grep 端口 | grep -v grep | awk '{print $1}' | xargs kill -9
[ root@localhost ~]
[ root@localhost projects]
[ root@localhost projects]
[ root@localhost mysite1]
manage.py mysite1
[ root@localhost mysite1]
Type 'manage.py help <subcommand>' for help on a specific subcommand.
Available subcommands:
[ auth]
changepassword
createsuperuser
[ contenttypes]
remove_stale_contenttypes
[ django]
check
compilemessages
.. .. ..
[ root@localhost mysite1]
Watching for file changes with StatReloader
Performing system checks.. .
System check identified no issues ( 0 silenced) .
You have 18 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.
August 04, 2024 - 14 :03:41
Django version 4.0 .10, using settings 'mysite1.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
此时,浏览器访问http://127.0.0.1:8000/,可看到django的启动页面
在启动服务的终端可以看见请求日志信息
[ root@localhost mysite1]
……省略一万字
February 21 , 2023 - 15 :27:45
Django version 2.2 .12, using settings 'mysite1.settings'
Starting development server at http://127.0.0.1:5000/
Quit the server with CONTROL-C.
此时,浏览器访问http://127.0.0.1:5000/,可看到django的启动页面
在启动服务的终端可以看见请求日志信息
项目结构解析
[ root@localhost projects]
manage.py
mysite1
__init__.py
settings.py
urls.py
wsgi.py
asgi.py
python3 manage.py runserver [ 端口]
python3 manage.py startapp
python3 manage.py migrate
setting.py配置文件
DEBUG、ALLOWED_HOSTS
DEBUG = True
DEBUG = False
ALLOWED_HOSTS = [ ]
ALLOWED_HOSTS = [ "*" ]
ALLOWED_HOSTS = [ '192.168.1.3' , '127.0.0.1' ]
]
DEBUG = True
ALLOWED_HOSTS = [ ]
]
此时,浏览器访问 http: // 内网IP: 8000 / abc. jpg
]
DEBUG = True
ALLOWED_HOSTS = [ "内网IP" ]
]
此时,浏览器访问 http: // 内网IP: 8000 / abc. jpg
其他公有配置
BASE_DIR = os. path. dirname( os. path. dirname( os. path. abspath( __file__) ) )
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
ROOT_URLCONF = 'mysite1.urls'
INSTALLED_APPS:指定当前项目中安装的应用列表
MIDDLEWARE:用于注册中间件
TEMPLATES:用于指定模板的配置信息
DATABASES:用于指定数据库的配置信息
例如:ALPAY_KEY = 'xxxx'
引入方式:from django. conf import settings
Django处理URL请求的过程
URL结构
作用:用来表示互联网上某个资源的地址
一般语法格式:
protocol://host[ :port] /path[ ?query] [
例如:https://cn.bing.com/dict/search?q= endpoint& FORM = BDVSP6& cc = cn
常用协议:
- https 通过安全的HTTPS访问该资源。格式 https://
- http 通过 HTTP 访问该资源。格式 http://
- file 资源是本地计算机上的文件。格式 file://
- 是指存放资源的服务器的域名系统( DNS) 主机名、域名或者IP地址
- 各种传输协议都有默认的端口号,省略时使用方案的默认端口。如https的默认端口是443,http的默认端口是80
例如:https://cn.bing.com/dict/search?q= endpoint& FORM = BDVSP6& cc = cn
- 由零或多个 / 符号隔开的字符串,一般用来表示主机上的一个目录或者文件地址
- 资源路径决定了服务器端如何处理这个请求
例如:https://cn.bing.com/dict/search?q= endpoint& FORM = BDVSP6& cc = cn
- 可选,键值对,用于给动态网页传递参数,如果有多个参数,用& 符号隔开,每个参数的名和值用 = 符号隔开
例如:https://cn.bing.com/dict/search?q= endpoint& FORM = BDVSP6& cc = cn
- 可选,字符串,用于指定网络资源的片段,类似于书签
- 用于页面内部跳转
主路由文件、视图文件
1 . 主路由文件由settings.py配置文件中的配置项ROOT_CONF决定,默认是项目同名目录下的urls.py
2 . 主路由文件通过定义urlpatterns变量来配置路由,该变量是一个定义了多个path( ) 函数的数组,用于匹配客户端访问的URL中的path
import django.urls import path
urlpatterns = [
path( "path01" , 视图文件.视图函数01) ,
path( "path02" , 视图文件.视图函数02) ,
]
1 . 视图文件是自定义的,一般为views.py,与主路由文件同目录。
2 . 视图文件中可以定义多个视图函数,被主路由文件引用。
3 . 视图函数用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应
from django.http import HttpResponse
def 视图函数01( request[ , 其它参数.. .] ) :
return HttpResponse对象
def 视图函数02( request[ , 其它参数.. .] ) :
return HttpResponse对象
Django处理URL请求的过程
浏览器地址栏 http: // 127.0 .0 .1 : 8000 / page/ 1234
Django处理过程:
1. Django根据settings. py配置文件中的ROOT_CONF找到主路由文件
2. Django加载主路由文件中的urlpatterns变量
3. 解析客户端访问的URL中的path,依次去匹配urlpatterns变量中的path,匹配到第一个合适的path则停止(匹配即停止)
4. 如果匹配成功:调用视图文件中对应的视图函数处理请求,返回响应
5. 如果全部匹配失败:返回404 响应
]
from django. contrib import admin
from django. urls import path
from . import views
urlpatterns = [
path( "admin/" , admin. site. url) ,
path( "page/2023/" , views. page_2023_view) ,
path( "page/2024/" , views. page_2024_view) ,
]
]
from django. http import HttpResponse
def page_2023_view ( request) :
html = "<h1>这是第一个页面</h1>"
return HttpResponse( html)
def page_2024_view ( request) :
html = "<h1>这是第二个页面</h1>"
return HttpResponse( html)
浏览器访问 http: // 127.0 .0 .1 : 8000 / page/ 2023 /
匹配path page/ 2023 / ,由views. py中的page_2023_view( ) 处理,返回"这是第一个页面"
浏览器访问 http: // 127.0 .0 .1 : 8000 / page/ 2024 /
匹配path page/ 2024 / ,由views. py中的page_2024_view( ) 处理,返回"这是第二个页面"
浏览器访问 http: // 127.0 .0 .1 : 8000 / page/ 2025 /
没有匹配的path,返回404
path()函数、path转换器、re_path()函数
path()函数
import django.urls import path
path( route, views, name = None)
path()函数示例
]
from django. urls import path
from . import views
urlpatterns = [
path( "" , views. index_view) ,
path( "page/1" , views. page1_view) ,
path( "page/2" , views. page2_view) ,
]
]
from django. http import HttpResponse
def index_view ( request) :
html = "<h1>这是我的首页</h1>"
return HttpResponse( html)
def page1_view ( request) :
html = "<h1>这是编号为1的网站</h1>"
return HttpResponse( html)
def page2_view ( request) :
html = "<h1>这是编号为2的网站</h1>"
return HttpResponse( html)
浏览器访问http: // 127.0 .0 .1 : 8000 / page/ 1 ,返回 这是编号为1 的网站
浏览器访问http: // 127.0 .0 .1 : 8000 / page/ 2 ,返回 这是编号为2 的网站
path转换器 关键字传参
语法:< 转换器类型:自定义名>
作用:若转换器类型匹配到对应类型的数据,则将数据按照"关键字传参" 的方式传递给视图函数
示例:` path( 'page/<int:abc>' , views.xxx) ` ,当匹配到page/正整数,则将` abc = 正整数` 传递给视图函数views.xxx
str
int
path
path转换器示例
]
from django. urls import path
from . import views
urlpatterns = [
path( "page/<int:pg>" , views. pagen_view) ,
]
]
from django. http import HttpResponse
def pagen_view ( request, pg) :
html = f"<h1>这是编号为 { pg} 的网站</h1>"
return HttpResponse( html)
浏览器访问http: // 127.0 .0 .1 : 8000 / page/ 3 ,返回 这是编号为3 的网站
浏览器访问http: // 127.0 .0 .1 : 8000 / page/ 4 ,返回 这是编号为4 的网站
path转换器示例:两个数的加减乘
]
from django. urls import path
from . import views
urlpatterns = [
path( "<int:n>/<str:op>/<int:m>" , views. cal_view) ,
]
]
from django. http import HttpResponse
def cal_view ( request, n, op, m) :
if op == "add" :
result = n + m
elif op == "sub" :
result = n - m
elif op == "mul" :
result = n * m
else :
return HttpResponse( "Your op is wrong!" )
return HttpResponse( f"<h1>计算结果为: { result} </h1>" )
浏览器访问http: // 127.0 .0 .1 : 8000 / 3 / abc/ 4 ,返回 Your op is wrong!
浏览器访问http: // 127.0 .0 .1 : 8000 / 3 / add/ 4 ,返回 计算结果为: 7
浏览器访问http: // 127.0 .0 .1 : 8000 / 3 / sub/ 4 ,返回 计算结果为: - 1
浏览器访问http: // 127.0 .0 .1 : 8000 / 3 / mul/ 4 ,返回 计算结果为: 12
path转换器示例:校验用户密码
]
from django. urls import path
from . import views
urlpatterns [
path( 'login/<str:user>/<str:pass>' , views. login_view)
]
]
from django. http import HttpResponse
def login_view ( request, user, pass ) :
if ( user == 'admin' ) and ( pass == '123abc' ) :
result = '<h1 style="color:green">登陆成功</h1>'
else :
result = '<h1 style="color:red">登陆失败</h1>'
return HttpResponse( result)
浏览器访问http: // 127.0 .0 .1 : 8000 / admin/ 123abc,返回 登陆成功
浏览器访问http: // 127.0 .0 .1 : 8000 / admin/ 123 ,返回 登陆失败
re_path()函数
from django.urls import re_path
re_path( r"正则表达式" , views, name = None)
re_path()函数示例:100以内的正整数加减乘
]
from django. urls import re_path
from . import views
urlpatterns = [
re_path( r"^(?P<n>\d{1,2})/(?P<op>\w+)/(?P<m>\d{1,2})$" , views. cal_view) ,
]
]
from django. http import HttpResponse
def cal_view ( request, n, op, m) :
n, m = int ( n) , int ( m)
if op == "add" :
result = n + m
elif op == "sub" :
result = n - m
elif op == "mul" :
result = n * m
else :
return HttpResponse( "Your op is wrong!" )
return HttpResponse( f"<h1>计算结果为: { result} </h1>" )
浏览器访问http: // 127.0 .0 .1 : 8000 / 13 / add/ 4 ,返回 计算结果为: 17
re_path()函数示例:获取生日
]
from django. urls import re_path
from . import views
urlpatterns [
re_path( r"^birthday/(?P<yead>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})$" , views. birthday) ,
re_path( r"^birthday/(?P<day>\d{1,2})/(?P<month>\d{1,2})/(?P<yead>\d{4})$" , views. birthday) ,
]
]
from django. http import HttpResponse
def birthday ( request, yead, month, day) :
return HttpResponse( f"<h1>生日为 { year} 年 { month} 月 { day} 日</h1>" )
浏览器访问http: // 127.0 .0 .1 : 8000 / birthday/ 2023 / 11 / 23 ,返回 生日为 2023 年11 月23 日
浏览器访问http: // 127.0 .0 .1 : 8000 / birthday/ 11 / 23 / 2023 ,返回 生日为 2023 年11 月23 日
HTTP协议的请求和响应
请求是指浏览器端通过HTTP协议发送给服务器端的数据。
响应是指服务器端接收到请求后做相应的处理后再回复给浏览器端的数据。
服务器可以利用Django框架,处理接收的请求并恢复给浏览器端。
请求
POST / post HTTP/ 1.1
HOST: httpbin. org
User- Agent: python- requests/ 2.24 .0
Accept- Encoding: gzip, deflate
Accept: * / *
Content- Type: application/ json
Content- Length: 62
Connection: keep- alive
{ "name" : "zhangsan" , "hobby" : "lisi" }
请求中的方法
根据HTTP标准,HTTP请求可以使用多种请求方法
HTTP1.0定义了三种请求方法:GET/POST/HEAD方法(最常用)
GET
HEAD
POST
HTTP1.1新增了五种请求方法:OPTIONS/PUT/DELETE/TRACE/CONNECT方法
PUT
DELETE
CONNECT
OPTIONS
TRACE
Django中的请求
请求在Django中实则就是视图函数的第一个参数,即HttpRequest对象
Django接收到http协议的请求后,会根据请求数据报文创建HttpRequest对象
HttpRequest对象通过属性描述了请求的所有相关信息
HttpRequest对象属性
视图函数用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应
from django.http import HttpResponse
def 视图函数01( request[ , 其它参数.. .] ) :
return HttpResponse对象
def 视图函数02( request[ , 其它参数.. .] ) :
return HttpResponse对象
request.path_info
request.get_full_path( )
request.method
request.GET
request.GET[ '键' ]
request.GET.getlist[ '键' ]
request.POST
request.request.FILES
request.COOKIES
request.session
request.body
request.scheme
request.META
request.META[ 'REMOTE_ADDR' ]
get请求
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_request" , views. test_request) ,
]
]
def test_request ( request) :
print ( "path info is:" , request. path_info)
print ( "method is:" , request. method)
print ( "full path:" , request. get_full_path( ) )
print ( "查询参数:" , request. GET)
print ( "只能获取一个:" , request. GET[ 'a' ] )
print ( "获取一组:" , request. GET. getlist[ 'a' ] )
print ( request. GET. get( 'c' , 'hello' ) )
return HttpResponse( "test request ok~" )
浏览器访问:http: // 127.0 .0 .1 : 8000 / test_request?a= 1 & b= 2 & a= 8
F12,'网络' ,查看'消息头'
post请求
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_get_post" , views. test_get_post)
]
]
form_html = '''
<form method='post' action='/test_get_post'>
用户:<input type='text' name='username'><br>
密码:<input type='text' name='password'><br>
<input type='submit' value='登陆'>
</form>
'''
def test_get_post ( request) :
if request. method == 'GET' :
return HttpResponse( form_html)
elif request. method == 'POST' :
print ( request. POST)
print ( '用户名:' , request. POST( 'username' ) )
print ( '用户名:' , request. POST. getlist( 'username' ) )
print ( '用户名:' , request. POST. get( 'username' ) )
return HttpResponse( '登陆成功' )
pass
else :
pass
return HttpResponse( 'test_get_post ok' )
浏览器访问:http: // 127.0 .0 .1 : 8000 / test_request
用户输入zhangsan,密码输入123456
F12,'网络' ,查看'消息头' 和'请求'
响应
状态码
常见的HTTP状态码(Http Status Code)
200 :请求成功
301 :永久重定向,资源/网页等被永久转移到其他URL地址
302 :临时重定向
404 :请求的资源/网页等不存在
500 :服务器内部错误
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为 5 种类型:
1 **
2 **
3 **
4 **
5 **
HttpResponse子类
构造函数格式:` HttpResponse( content= 响应体, content_type = 响应体数据类型, status = 状态码) `
作用:向客户端浏览器返回响应,同时携带响应体内容
参数:
content:表示返回的内容
content_type:指定返回数据的MIME类型(缺省text/html)
status_code:返回的HTTP响应状态码(缺省200)
text/html
text/plain
text/css
text/javascript
application/json
multipart/form-data
HttpResponseRedirect( )
HttpResponseNotModified( )
HttpResponseBadRequest( )
HttpResponseForbidden( )
HttpResponseNotFound( )
HttpResponseServerError( )
]
from django. urls import path
from . import views
urlpatterns = [
path( 'page/1/' , views. page_1_view) ,
path( "test_request" , views. test_request) ,
]
]
from django. http import HttpResponse, HttpResponseRedirect
def page_1_view ( request) :
return HttpResponse( 'this is page_1_view' )
def test_request ( request) :
print ( "path info is:" , request. path_info)
print ( "method is:" , request. method)
print ( "query string:" , request. GET)
print ( "full path:" , request. get_full_path( ) )
return HttpResponseRedirect( "/page/1" )
浏览器访问http: // 127.0 .0 .1 : 8000 / test_request,跳转到http: // 127.0 .0 .1 : 8000 / page/ 1 ,返回this is page_1_view
Django处理请求 request.method
if request. method == "GET" :
处理GET请求时的业务逻辑
elif request. method == "POST" :
处理POST请求时的业务逻辑
else :
其他请求业务逻辑
处理GET请求
GET请求动作,一般用于向服务器获取数据,能够产生GET请求的场景:
1. 浏览器地址栏中输入URL,回车后
2. html跳转链接`< a href= "地址?参数=值&参数=值" / > `
3. html表单form中的method为 get
GET请求方式中,如果有数据需要传递给服务器,通常会用查询字符串(QueryString)传递
格式:`URL地址?参数1 = 值1 & 参数2 = 值2 `,如:http: // 127.0 .0 .1 : 8000 / page1?a= 1 & b= 2
服务器端使用GET来获取客户端GET请求的数据,常用方法:
request. GET
request. GET[ "参数名" ]
request. GET. getlist( "参数名" )
request. GET. get( "参数名" , "参数值" )
page?a= 100 & b= 200 & c= 300 & b= 400
request. GET
request. GET[ "a" ]
request. GET. getlist( "a" )
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_get_post" , views. test_get_post) ,
]
]
from django. http import HttpResponse
def test_get_post ( request) :
if request. method == "GET" :
print ( "1" , request. GET)
print ( "2" , request. GET[ "a" ] )
print ( "3" , request. GET. getlist( 'a' ) )
print ( "4" , request. GET. get( "c" , "no c" ) )
elif request. method == "POST" :
pass
else :
pass
return HttpResponse( "--test get post is ok --" )
浏览器访问http: // 127.0 .0 .1 : 8000 / test_get_post?a= 400
浏览器访问http: // 127.0 .0 .1 : 8000 / test_get_post
浏览器访问http: // 127.0 .0 .1 : 8000 / test_get_post?a= 100 & a= 200 & a= 300
处理POST请求
POST请求动作,一般用于向服务器提交大量/ 隐私数据,客户端通过表单等POST请求将数据传递给服务器端,如:
< form method= 'post' action= '/test_get_post' >
用户:< input type = 'text' name= 'username' > < br>
密码:< input type = 'text' name= 'password' > < br>
< input type = 'submit' value= '登陆' >
< / form>
服务器端使用POST来接收客户端POST请求的数据,常用方法
request. POST[ "参数名" ]
request. POST. getlist( "参数名" )
request. POST. get( "参数名" , "参数值" )
注意:Django配置中取消csrf验证,否则Django将会拒绝客户端发来的POST请求,报403 响应
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_get_post" , views. test_get_post) ,
]
]
from django. http import HttpResponse
POST_FORM = """
<form method="post" action="/test_get_post">
用户名: <input type="text" name="uname">
<input type="submit" value="提交">
</form>
"""
def test_get_post ( request) :
if request. method == "GET" :
print ( request. GET)
print ( request. GET. getlist( "a" ) )
print ( request. GET. get( "c" , "no c" ) )
return HttpResponse( POST_FORM)
elif request. method == "POST" :
print ( "uname is:" , request. POST. get( "uname" ) )
return HttpResponse( "post is ok~" )
else :
pass
return HttpResponse( "--test get post is ok --" )
浏览器访问http: // 127.0 .0 .1 : 8000 / test_get_post,返回表单数据
填写表单数据,点击提交,发送POST请求,查看浏览器显示内容,POST请求失败,403 响应
取消csrf验证:注释掉 settings. py 中的 MIDDLEWARE 中的 CsrfViewsMiddleWare 的中间件,重新提交表单数据,数据提交成功
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware' ,
'django.contrib.sessions.middleware.SessionMiddleware' ,
'django.middleware.common.CommonMiddleware' ,
'django.contrib.auth.middleware.AuthenticationMiddleware' ,
'django.contrib.messages.middleware.MessageMiddleware' ,
'django.middleware.clickjacking.XFrameOptionsMiddleware' ,
]
Django模板层
设计模式 MVC和MTV
MVC设计模式把Web框架分为三个基础部分:
- M 模型层(Model):主要用于对数据库层的封装
- V 视图层(View):用于向用户展示结果(what+ how)
- C 控制层(Controller):用于处理请求获取数据,返回结果
作用:降低模块间的耦合度(解耦)
MTV和MVC本质上是一样的,MTV代表 Model- Template- View (模型- 模板- 视图)模式
- M 模型层(Model):负责与数据库交互
- T 模板层(Template):负责呈现内容到浏览器(how)
- V 视图层(View):是核心,负责接收请求,获取数据,返回结果(what)
浏览器发送请求给服务端
服务端中的控制器C收到请求,根据请求去模型层M获取数据,模型层M去数据库获取数据并封装后返回给控制器C,控制器C去视图层V获取模板,将从模型层M获取的数据填充到从视图层V获取的模板中,最后将结果响应返回给浏览器
服务端中的视图层V收到请求,从模板层T获取模板,根据请求去模型层M获取数据,模型层M去数据库获取数据并封装后返回给视图层V,视图层V将从模型层M获取的数据填充到从模板层T获取的模板中,最后将结果响应返回给浏览器
模板层
模板是可以根据字典数据"动态变化的HTML网页" ,模板可以根据视图中"传递的字典数据动态生成相应的HTML页面"
修改 settings. py 中 TEMPLATES 配置项
BACKEND
DIRS
APP_DIRS
OPTIONS
]
]
BASE_DIR = os. path. dirname( os. path. dirname( os. path. abspath( __file__) ) )
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' ,
] ,
} ,
} ,
]
模板渲染方式
]
from django. http import HttpResponse
from django. template import loader
def test_html ( request) :
t = loader. get_template( "test_html.html" )
html = t. render( )
return HttpResponse( html)
]
from django. shortcuts import render
def test_html ( request) :
return render( request, "test_html.html" )
示例:模板渲染
]
]
BASE_DIR = os. path. dirname( os. path. dirname( os. path. abspath( __file__) ) )
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' ,
] ,
} ,
} ,
]
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
< h3> 我是模板层!!!< / h3>
< / body>
< / html>
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_html" , views. test_html) ,
]
]
from django. http import HttpResponse
def test_html ( request) :
from django. template import loader
t = loader. get_template( "test_html.html" )
html = t. render( )
return HttpResponse( html)
]
def test_html ( request) :
from django. shortcuts import render
return render( request, "test_html.html" )
浏览器访问http: // 127.0 .0 .1 : 8000 / test_html
模板层—变量 render(request, "模板", 字典类型数据)
视图函数中可以将Python变量封装到"字典" 中传递到模板,样例:
写法一:直接创建字典
def xxx_view( request) :
dic = {
"变量1" : "值1" ,
"变量2" : "值2" ,
}
return render( request, 'xxx.html' , dic)
写法二:使用locals( ) 传递同名键值的字典{ '变量1' : 变量1, '变量2' : 变量2}
def xxx_view( request) :
变量1 = 值1
变量2 = 值2
return render( request, 'xxx.html' , locals( ))
示例看 模板层-标签,if标签,示例二;算数运算
模板中可以使用 { { 变量名 } } 的语法调用视图函数传进来的变量
当views.py封装到"字典" 中的变量的值的"类型" 不同时,模板html中调用变量时的写法不同:
数值或字符串类型:` { { 变量名 } } `
列表类型:` { { 变量名.索引 } } `
字典类型:` { { 变量名.key名 } } `
方法类型:` { { 变量名 } } `
类类型:` { { 变量名.方法名 } } `
示例一:模板调用视图函数的变量
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_html" , views. test_html) ,
]
]
def test_html ( request) :
from django. shortcuts import render
dic = { "username" : "nfx" , "age" : 18 }
return render( request, "test_html.html" , dic)
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
< h3> 我是模板层!!!< / h3>
< !- - { "username" : "nfx" , "age" : 18 } ,使用{ { 变量名} } 来调用视图传进来的变量 - - >
< p> { { username } } < / p>
< p> { { age } } < / p>
< / body>
< / html>
浏览器访问http: // 127.0 .0 .1 : 8000 / test_html
示例二:不同变量类型的调用写法
]
from django. urls import path
from . import views
urlpatterns [
path( 'test_html_param' , views. test_html_param)
]
]
from django. shortcuts import render
def test_html_param ( request) :
dict = { }
ditc[ 'name' ] = 'Tom'
dict [ 'age' ] = 20
dict [ 'lis' ] = [ 'a' , 'b' ]
dict [ 'dic' ] = { 'zhangsan' : 10 , 'lisi' : 15 }
dict [ 'func' ] = say
dict [ 'obj' ] = Dog( )
return render( request, 'test_html_param.html' , dict )
def say ( ) :
return 'hello'
class Dog :
def wang ( ) :
return 'wangwang'
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
< h1> this is test_html_param < / h1>
< p> { { name } } < / p>
< p> { { age } } < / p>
< p> { { lis. 0 } } < / p>
< p> { { dic. zhangsan } } < / p>
< p> { { func } } < / p>
< p> { { obj. wang } } < / p>
< / body>
< / html>
浏览器访问http: // 127.0 .0 .1 : 8000 / test_html_param
this is test_html_param
Tom
20
a
10
hello
wangwang
模板层—标签
标签作用:将一些服务器端的功能嵌入到模板层,例如流程控制等
标签语法:
{ % 标签 %}
.. .. ..
{ % 结束标签 %}
条件 if 标签
{ % if 条件表达式1 % }
. . .
{ % elif 条件表达式2 % }
. . .
{ % elif 条件表达式3 % }
. . .
{ % else % }
. . .
{ % endif % }
注意:
1. if 条件表达式里可以用的运算符:
== 、!= 、< 、> 、<= 、>=
in 、not in
is 、is not
not 、and 、or
注意:运算符两侧要有空格
2. if 条件表达式中,使用字典的键时,直接使用`键名`,而不是`{ { 键名 } } `
2. 在 if 标记中使用实际括号是无效的语法,如果需要指示优先级,则应使用嵌套的 if 标记
示例一:比大小
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_if" , views. test_if) ,
]
]
from django. shortcuts import render
def test_if ( request) :
dic = { }
dic[ "x" ] = request. GET[ "tem" ]
return render( request, "test_if_for.html" , dic)
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
{ % if x > 20 % } < !- - 注意:if 条件表达式中,使用字典的键时,直接使用`键名` - - >
今天天气非常好
{ % elif x <= 20 and x > 10 % }
今天天气很好
{ % else % }
今天天气不好
{ % endif % }
< / body>
< / html>
浏览器访问http: // 127.0 .0 .1 : 8000 / test_if?tem= 25
浏览器访问http: // 127.0 .0 .1 : 8000 / test_if?tem= 15
浏览器访问http: // 127.0 .0 .1 : 8000 / test_if?tem= 10
示例二:算数运算
]
from django. urls import path
from . import views
urlpatterns = [
path( "mycal" , views. test_mycal) ,
]
]
from django. shortcuts import render
def test_mycal ( request) :
if request. method == "GET" :
return render( request, "mycal.html" )
elif request. method == "POST" :
x = int ( request. POST[ "xx" ] )
y = int ( request. POST[ "yy" ] )
op = request. POST[ "op" ]
result = 0
if op == "add" :
result = x + y
elif op == "sub" :
result = x - y
elif op == "mul" :
result = x * y
elif op == "div" :
result = x / y
return render( request, "mycal.html" , locals ( ) )
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
< form action= "/mycal" method= "post" >
< - - 实际action为"http://ip:端口/mycal" - - >
< !- - 注意method= "post" ,request. method为"POST" - - >
< input type = "text" name= "xx" value= "{{ x }}" >
< !- - 这里的value,用于处理post请求提供新页面时,保持输入框的显示内容为输入内容- - >
< !- - value显示的值,数值类型的变量x,使用值{ { x } } - - >
< select name= "op" >
< option value= "add" { % if op == "add" % } selected{ % endif % } > 加< / option>
< !- - 注意:if 条件表达式中,使用字典的键时,直接使用`键名` - - >
< option value= "sub" { % if op == "sub" % } selected{ % endif % } > 减< / option>
< option value= "mul" { % if op == "mul" % } selected{ % endif % } > 乘< / option>
< option value= "div" { % if op == "div" % } selected{ % endif % } > 除< / option>
< !- - 这里的if 判断和selected,用于处理post请求提供新页面时,保持下拉选框op的选择- - >
< / select>
< input type = "text" name= "yy" value= "{{ y }}" > 等于 < span> { { result } } < / span>
< div> < input type = "submit" value= "开始计算" > < / div>
< !- - 提交按钮将值赋予给xx、op、yy - - >
< / form>
< / body>
< / html>
浏览器访问http: // 127.0 .0 .1 : 8000 / mycal
示例二的思路
1 . 通过request.method来判断是get请求还是post请求,然后返回不同render对象
要保持页面一致,因此不同render对象使用同一模板
2 . get请求:访问URL
处理get请求:提供对应的模板页面
3 . post请求:提供表单,通过输入框、下拉选框等来输入值,提交键将值赋予变量
处理post请求,获取变量的值赋予给字典的键,将计算结果赋予给字典的一个键,在模板中使用字典的键值
循环 for 标签和forloop变量
{ % for 变量 in 可迭代对象 % }
. . . 循环语句
{ % empty % }
. . . 可迭代对象无数据时填充的语句
{ % endfor % }
forloop. counter
forloop. counter( )
forloop. revcounter
forloop. revcounter( )
forloop. first
forloop. last
forloop. parentloop
示例:for循环和forloop的使用
]
from django. urls import path
from . import views
urlpatterns = [
path( "test_for" , views. test_for) ,
]
]
from django. shortcuts import render
def test_for ( request) :
dic = { }
dic[ "lis" ] = [ "zhangsan" , "lisi" , "wangwu" ]
return render( request, "test_if_for.html" , dic)
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< title> Title< / title>
< / head>
< body>
{ % for name in lis % }
{ % if forloop. first % } - - - - - - - { % endif % }
< p> { { forloop. counter } } { { name } } < / p>
{ % if forloop. last % } == == == = { % endif % }
{ % empty % }
当前没数据
{ % endfor % }
< / body>
< / html>
浏览器访问http: // 127.0 .0 .1 : 8000 / test_for
- - - - - - -
1 zhangsan
2 lisi
3 wangwu
== == == =
模板继承 extends标签和block标签
通过模板继承,子模板可以直接继承父模板的全部内容然后复用,也可以重写父模板中的块(允许被重写的部分)
注意:模板继承时,"服务器端的动态内容无法继承"
允许被重写的内容:使用block标签标识可以被重写的内容
{ % block 块名 % }
. . . 可以被重写的内容
{ % endblock % }
继承模板:使用extends标签(写在模板文件的第一行)继承父模板全部内容
{ % extends "父模板" % }
例如:{ % extends "base.html" % }
重写父模板中的块:使用block标签指定重写的内容
{ % block 父模板的块名 % }
. . . 新内容
{ % endblock % }
示例:主页跳转子页面
]
from django. urls import path
from . import views
urlpatterns = [
path( "base_index" , views. base_view) ,
path( "music_index" , views. music_view) ,
path( "sport_index" , views. sport_view) ,
]
]
from django. shortcuts import render
def base_view ( request) :
return render( request, "base.html" )
def sport_view ( request) :
return render( request, "sport.html" )
def music_view ( request) :
return render( request, "music.html" )
]
< !DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
{ % block mytitle % } < !- - block可以被重写的内容,块名mytitle- - >
< title> 主页< / title>
{ % endblock % }
< / head>
< body>
< a href= "/base_index" > 首页< / a>
< !- - 这里的href实际是"http://ip:端口/base_index" - - >
< a href= "/music_index" > 音乐频道< / a>
< !- - 这里的href实际是"http://ip:端口/music_index" - - >
< a href= "/sport_index" > 体育频道< / a>
< !- - 这里的href实际是"http://ip:端口/sport_index" - - >
< br>
{ % block info % } < !- - block可以被重写的内容,块名info- - >
这是主页
{ % endblock % }
< br>
< h3> 这是底部< / h3>
< / body>
< / html>
]
{ % extends "base.html" % } < !- - 继承父模板base. html的全部内容- - >
{ % block mytitle % } < !- - 重写块mytitle- - >
< title> 体育频道< / title>
{ % endblock % }
{ % block info % } < !- - 重写块info- - >
欢迎来到体育频道
{ % endblock % }
]
{ % extends "base.html" % } < !- - 继承父模板base. html的全部内容- - >
{ % block mytitle % } < !- - 重写块mytitle- - >
< title> 音乐频道< / title>
{ % endblock % }
{ % block info % } < !- - 重写块info- - >
欢迎来到音乐频道
{ % endblock % }
浏览器访问http: // 127.0 .0 .1 : 8000 / base_index,点击体育频道,跳转http: // 127.0 .0 .1 : 8000 / sport_index
浏览器访问http: // 127.0 .0 .1 : 8000 / base_index,点击音乐频道,跳转http: // 127.0 .0 .1 : 8000 / music_index