URL和视图函数
URL(Uniform Resource Locator)
组成:protocol://hostname[:port]/path[?query][#fragment]
书写规范:
-绝对地址:http://127.0.0.1:8000/test_html_param/Paul
-相对地址:
1. ‘/page/1’ – 结果为:http://127.0.0.1:8000/ + /page/1, 在端口后添加
2. ‘page/1’ – 结果为:http://127.0.0.1:8000/test_html_param/ + page/1,在最后一个’/'后添加
test_url.html
<a href="http://127.0.0.1:8000/url_result">绝对地址</a>
<a href="/url_result">带/的相对地址</a>
<a href="url_result">不带/相对地址</a>
<br>
<a href="{%url 'tr' %}">URL 反向解析</a>
test_url_result.html
<p>Test result!</p>
urls.py
path('test/url', test_url),
# path('url_result', test_url_result),
# django 重定向需要repath
# re_path()中只是赋予一个别名,使用别名是在html中
re_path('url_result',test_url_result, name='tr'),
views.py
def test_url(request):
from django.shortcuts import render
return render(request, "test_url.html")
def test_url_result(request):
from django.shortcuts import render
return render(request, 'test_url_result.html')
URL反向解析是指在视图或模板中,使用re_path定义名称来动态查找或计算出相对应的路由,
re_path(route, views, name=“别名”)
{% url '别名' %}
{% url '别名' '参数值1' '参数值2' %}
<a href="{%url 'tr' %}">URL 反向解析</a>
处理URL请求
- Django从配置文件中跟据ROOT_URLCONF找到主路由文件;默认情况下为urls.py
- Django 加载主路由文件中的urlpatterns变量【包含很多路由的数组】
- 依次匹配urlpatterns中的path【from diango,urls import path,repath】,匹配到第一个合适的路由中断匹配
// path('url',视图函数)
// re_path('url',视图函数,别名)
path('admin/', admin.site.urls)
re_path('url_result',test_url_result, name='tr')
- 匹配成功 - 调用对应的视图函数处理请求,返回响应
- 匹配失败 - 返回404响应
视图函数
视图函数是用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应的函数。
// 语法:
def home_view(request,[其他参数]):
html = "<h1>This is my home!</h1>"
return HttpResponse对象
path转换器
转换器类型:str(匹配除了‘/’之外的非空字符串),int(匹配0或任何正整数,返回一个int),slug,path(匹配包括‘/’的非空字符串)。
// 语法 <转换器类型:自定义名>
// path('page/<int:page>',page_n) 按照关键字传参
def page_view(request, pg):
# html = "<h1>This is number "+str(pg) + " site!</h1>"
html = "<h1>This is number %s site!</h1>" % (pg)
return HttpResponse(html)
path('page/<int:pg>',page_view),
// 小型计算器
def page_cal(request, num1, cal, num2):
if cal == "add":
sum = int(num1) + int(num2)
elif cal == "mul":
sum = int(num1) * int(num2)
elif cal == "sub":
sum = int(num1) - int(num2)
html = "<h1>The result is %s !</h1>" % (sum)
return HttpResponse(html)
path('<int:num1>/<str:cal>/<int:num2>',page_cal)
请求
请求方法包括GET、POST和HEAD方法(以及其他五种不常用的请求:OPTIONS、PUT、DELETE、TRACE、CONNECT)
请求在Django中就是视图函数中第一个参数request,即HttpRequest对象,通过属性描述了请求的所有相关信息,eg:
# request.path_info 是request的路径
# request.method 是request的方法
# request.GET 是QueryDict查询字典的对象,包含get请求方式的所有数据
如http://127.0.0.1:8000/test_request?a=1&&b=2获取{‘a’:['1'],'b':['2']},元素都是数组
# request.POST 是QueryDict查询字典的对象,包含post请求方式的所有数据
# request.FILES 类似于字典的对象,包含所有的上传文件信息
# GET请求只是从服务器读取页面的请求
# POST请求是用户需要提交表单时使用的请求
# COOKIES:Python字典,包含所有的cookie,键和值都为字符串
# session:类似字典的对象,表示当前的会话
# body:字符串,请求体的内容(POST或PUT)
# scheme:请求协议(‘http’/'https')
# request.get_full_path():请求的完整路径
# request.META:请求中的元数据(消息头)
request.META['REMOTE_ADDR']:客户端IP地址
def test_request(request):
print("Path info is ", request.path_info)
print("Method is ", request.method)
print("Querystring is ", request.GET)
print("Request body is ", request.body)
return HttpResponse("Test request result!")
path("test_request",test_request)
无论是GET还是POST,统一由视图函数接受请求,用request.method判断
GET请求
GET 请求指定的页面信息,并返回实体主体。
能够产生GET请求的场景:
- 浏览器地址栏中输入URL,回车后
- <a href="地址?参数=值&参数=值"
- form表单中的method为get
if request.method == 'GET':
print(request.GET)
print(request.GET['a'])
print(request.GET.get('c', 'no c'))
print(request.GET.getlist('c'))
return HttpResponse(request.method)
http://127.0.0.1:8000/test_get_post?c=263&a=1000&c=24294的输出结果
POST请求
向指定资源提交数据进行处理请求,数据被包含在请求体中,POST请求可能会导致新的资源的建立和/或已有资源的修改
POST_FORM = '''
<form method='post' action='test_get_post'>
用户名:<input type='text' name='usname'>
<input type='submit' value='提交'>
</form>
'''
def test_get_post(request):
if request.method == 'GET':
return HttpResponse(POST_FORM)
elif request.method == 'POST':
print("usname is ", request.POST['usname'])
return HttpResponse("Post is ok!")
http://127.0.0.1:8000/test_get_post的运行结果:
首先GET请求获得空白表单,其次提交之后POST请求提交表单
响应
响应状态码:-200 请求成功
-301 永久重定向,资源被永久转移到其他URL
-302 临时重定向
-404 请求的资源不存在
-500 内部服务器错误
构造函数格式:HttpResponse(content = 响应体, content_type = 响应体数据类型, status = 状态码)
常用的Content_Type类型:
HttpResponse的子类:from django.http import HttpResponse, HttpResponseRedirect
Django的设计模式
传统的MVC(模型-视图-控制器)
# 降低模块之间的耦合度
# Model: 主要用于对数据库层的封装
# View: 用于向用户展示结果
# Controller: 用于处理请求、获取数据、返回结果
Django的MTV模式
# 降低模块之间的耦合度
# Model: 负责与数据库交互
# Template: 负责呈现内容到浏览器(HTML、CSS)
# View: 核心,负责接收请求、获取数据、返回结果
# 主路由相当于Controller
模板层
模板配置
- 创建模板文件夹<项目名>/templates
- 在settings.py中TEMPLATES配置项
- BACKEND:指定模板引擎
- DIRS:模板的搜索目录
- APP_DIRS:是否要在应用中的templates文件夹中搜索模板文件
- OPTIONS:有关模板的选项
- 配置项中需要修改的部分
设置DIRS:‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)]
模板的加载方式
方案一:通过loader获取模板,通过HttpResponse进行响应
模板:
from django,template import loader
t = loader.get_template("模板文件名")
html = t.render(字典数据)
return HttpResponsse(html)
样例:
# loader对象的render方法
from django.template import loader
t = loader.get_template('test_html.html')
html = t.render()
return HttpResponsse(html)
方案二:使用render()直接加载响应模板
样例:
from django.shortcuts import render
dic = {
'username': 'paul',
'age': 21
}
# return render(request, '模板文件名', 字典)
return render(request, 'test_html.html', dic)
在视图函数中,直接使用locals()直接获得视图函数的变量字典
return render(request, 'test_html.html',locals())
在模板中,通过使用{
{变量名}}的语法,调用视图函数中的变量
模板的变量
能传递到模板中的数据类型:str(字符串),int(整型),list(数组),tuple(元组),dict(字典),func(方法),obj(类实例化的对象)
<h3>int 是 {
{int|add:'2'}} </h3> <!-- add:'n' 过滤器-->
<h3>str 是 {
{str|upper}} </h3> <!-- upper 过滤器-->
<h3>lst 是 {
{lst}} </h3>
<h3>lst 是 {
{lst.0}} </h3>
<h3>dict 是 {
{dict}} </h3>
<h3>dict['a'] 是 {
{dict.a}} </h3>
<h3>function 是 {
{func}} </h3>
<h3>class_obj 是 {
{class_obj.say}} </h3>
<h3>Script 是 {
{script|safe}} </h3><!-- safe 过滤器, 不对字符串进行html转译,Django默认开启字符串转译-->
from django.shortcuts import render
dic = {}
dic['int'] = 88
dic['str'] = 'username'
dic['lst'] = ['Tom', 'Jerry', 'Lily']
dic['dict'] = {'a': 9, 'b':7}
dic['func'] = say_hi
dic['class_obj'] = Dog()
dic['script'] = '<script>alter(1111)</script>'
return render(request, 'test_html_param.html', dic)
def say_hi():
return "hello"
class Dog:
def say(self):
return "nihao!"
模板的标签
if 标签
def test_if_for(request):
from django.shortcuts import render
dic = {}
dic['x'] = 10
return render(request, 'test_if_for.html', dic)
模板文件中
{% if x > 10 %}
今天天气很好
{% else %}
今天天气非常好
{% endif %}
<form action="/if_cal" method="post">
<input type="text" name="x" value={
{x}}>
<option value="add" {% if op == 'add' %} selected {% endif %}> + 加</option>
<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>
<input type="text" name="y" value={
{y}}> = <span>{
{result}}</span>
<div>
<input type="submit" value="开始计算">
</div>
</form>
def if_cal(request):
from django.shortcuts import render
if request.method == 'GET':
return render(request, 'if_cal.html')
else:
x = int(request.POST['x'])
y = int(request.POST['y'])
op = request.POST['op']
if op == 'add':
result = x + y
elif op == 'sub':
result = x - y
elif op == 'mul':
result = x * y
else:
result = x / y
# locals() 把变量封装成一个字典
# dic = {'x': x, 'y': y, 'op': op, 'result': result}
return render(request, 'if_cal.html', locals())
for 标签
语法:
{% for 变量 in 可迭代对象 %}
循环语句
{% empty %}
可迭代对象无数据时填充的语句
{% endfor %}
def test_if_for(request):
from django.shortcuts import render
dic = {}
dic['lst'] = ['Tom','Jack','Jerry']
return render(request, 'test_if_for.html', dic)
{% for name in lst%}
{% if forloop.first %} ########### {%endif%}
<p>{
{forloop.counter}} {
{name}}</p>
{% if forloop.last %} ********** {%endif%}
{% empty %}
Now Empty!
{% endfor %}
内置变量 - forloop
模板过滤器
定义:在变量输出时对变量的值进行处理
作用:可以通过使用过滤器来改变变量的输出和显示
语法:{
{变量 | 过滤器1:'参数值1'| 过滤器2:'参数值'2'}}
<h3>int 是 {
{int|add:'2'}} </h3> <!-- add:'n' 过滤器-->
<h3>str 是 {
{str|upper}} </h3> <!-- upper 过滤器-->
<h3>lst 是 {
{lst}} </h3>
<h3>lst 是 {
{lst.0}} </h3>
<h3>dict 是 {
{dict}} </h3>
<h3>dict['a'] 是 {
{dict.a}} </h3>
<h3>function 是 {
{func}} </h3>
<h3>class_obj 是 {
{class_obj.say}} </h3>
<h3>Script 是 {
{script|safe}} </h3><!-- safe 过滤器, 不对字符串进行html转译,Django默认开启字符串转译-->
from django.shortcuts import render
dic = {}
dic['int'] = 88
dic['str'] = 'username'
dic['lst'] = ['Tom', 'Jerry', 'Lily']
dic['dict'] = {'a': 9, 'b':7}
dic['func'] = say_hi
dic['class_obj'] = Dog()
dic['script'] = '<script>alter(1111)</script>'
return render(request, 'test_html_param.html', dic)
def say_hi():
return "hello"
class Dog:
def say(self):
return "nihao!"
模板的继承
模板继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相对应的块。
语法: