python之Django
Posted saoqiang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之Django相关的知识,希望对你有一定的参考价值。
1 Django基础一之web框架的本质
Django 、Flask 这些就是Python语言的web 框架。
1.1web框架的本质
Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。
1.1.1什么是 Web 服务器?
平时我们都是通过浏览器(比如Chrome,Firefox等)上网的,当我们在浏览器的地址栏里输入地址后,会得到一个网页。
这个网页就是 web 服务器返回给我们的,而浏览器就称为客户端,当我们输入网址并按下回车后,就像web服务器发送了一个web请求。
这种模式成为 B/S 模式 ,即 Browse / Server 模式
在浏览器中输入地址、按回车后,按下F12 就是看到如下信息
下面就让我们来目睹整个过程吧
- 建立连接:客户机通过TCP/IP协议建立到服务器的TCP连接。
- 请求过程:客户端向服务器发送HTTP协议请求包(Request),请求服务器里的资源文档。
- 应答过程:服务器向客户机发送HTTP协议应答包(Response),如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端。由客户端解释HTML文档,在客户端屏幕上渲染图形结果。
- 关闭连接:客户机与服务器断开。
这里Request 和 Response 都需要遵守 HTTP 协议,关于 HTTP 协议的详细内容,可以读读《HTTP 权威指南》
但是实际中的 Web 服务器远远比上面示例的复杂的多,因为要考虑的因素实在是太多了,比如:
- 缓存机制:讲一些经常被访问的页面缓存起来,提高响应速度;
- 安全:防止黑客的各种攻击,比如 SYN Flood 攻击;
- 并发处理:如何响应不同客户端同时发起的请求;
- 日志:记录访问日至,方便做一些分析。
目前在UNIX和LINUX平台下使用最广泛的免费 Web 服务器有Apache和 Nginx 。而这些软件都是遵循遵守 HTTP 协议的。
所以可以称他们为HTTP服务器,只是可以通过HTTP协议语言的解析转换。
https://www.cnblogs.com/clschao/articles/9230431.html
1.1.2Web 应用程序?
Web 服务器接受 Http Request,返回 Response,很多时候 Response 并不是静态文件,因此需要有一个应用程序根据 Request 生成相应的 Response。这里的应用程序主要用来处理相关业务逻辑,读取或者更新数据库,根据不同 Request 返回相应的 Response。注意这里并不是 Web 服务器本身来做这件事,它只负责 Http 协议层面和一些诸如并发处理,安全,日志等相关的事情。
应用程序可以用各种语言编写(Java, PHP, Python, Ruby等),这个应用程序会从Web服务器接收客户端的请求,处理完成后,再返回响应给Web服务器,最后由Web服务器返回给客户端。整个架构如下:
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。
1.1.3Web 框架
? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。
? 以 python web 框架 flask 为例,框架本身并不限定我们用哪种架构来组织我们的应用,不过其中一种比较经典的Web框架 Flask 采用了 MVC 架构,可以很好地支持以 MVC 方式组织应用。
- 用户输入 URL,客户端发送请求
控制器(Controller)
首先会拿到请求- 然后用
模型(Models)
从数据库取出所有需要的数据,进行必要的处理,将处理后的结果发送给视图(View)
- 视图利用获取到的数据,进行渲染生成 Html Response返回给客户端。
1.2基于socket自定义web框架
待定
1.3 模板渲染JinJa2
1.4MVC和MTV框架
1.4.1MVC
Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:
1.4.2MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是值:
- M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
- T 代表模板 (Template):负责如何把页面展示给用户(html)。
- V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
一般是用户通过浏览器向我们的服务器发起一个请求(request),这个请求回去访问视图函数,(如果不涉及到数据调用,那么这个时候视图函数返回一个模板也就是一个网页给用户),视图函数调用模型,模型去数据库查找数据,然后逐级返回,视图函数把返回的数据填充到模板中空格中,最后返回网页给用户。
1.5 Django下载安装 创建项目应用
1.5.1Django下载安装
1.5.1.1 cmd下载
第一种 cmd 输入python 进入 python解释器
输入pip3 install django==1.11.9
pip国内的一些镜像
阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/
临时使用:
可以在使用pip的时候在后面加上-i参数,指定pip源
修改源方法
pip3 install django==1.11.9
卸载djange
pip uninstall django
1.5.1.2pycham下载
File | Settings | Project: un1 | Project Interpreter
添加django
勾选这个Specify version 选择历史版本
1.5.2创建djange项目
1.5.2.1pythcm创建
注意不要选择虚拟环境
1.5.2.2终端创建
创建项目
django-admin startproject mysite 创建了一个名为"mysite"的Django 项目
启动项目
启动项目
python manage.py runserver 默认是127.0.0.1:8000
python manage.py runserver 127.0.0.1 默认端口号是8000
python manage.py runserver 127.0.0.1:8001
当前目录下会生成mysite的工程,目录结构如下:(大家注意昂,pip下载下来的django你就理解成一个模块,而不是django项目,这个模块可以帮我们创建django项目)
?
- manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库,启动关闭项目与项目交互等,不管你将框架分了几个文件,必然有一个启动文件,其实他们本身就是一个文件。
- settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
- urls.py ----- 负责把URL模式映射到应用程序。
- wsgi.py ---- runserver命令就使用wsgiref模块做简单的web server,后面会看到renserver命令,所有与socket相关的内容都在这个文件里面了,目前不需要关注它。
1.5.3创建应用
python manage.py startapp blog #通过执行manage.py文件来创建应用blog,执行这句话一定要注意,你应该在这个manage.py的文件所在目录下执行这句话,因为其他目录里面没有这个文件
python manage.py startapp blog2 #每个应用都有自己的目录,每个应用的目录下都有自己的views.py视图函数和models.py数据库操作相关的文件
我们现在只需要看其中两个文件
models.py :之前我们写的那个名为model的文件就是创建表用的,这个文件就是存放与该app(应用)相关的表结构的
views.py :存放与该app相关的视图函数的
1.6基于Django的简单小示例
第1步 先配置setting.py文件中的INSTALLED_APPS
第2步 配置urls.py文件 路径分发
第3步 配置视图,views.py 写自己的逻辑 返回html页面 还是重定向 等等
第4步 创建 对应的html页面
注意点 from表单 不添提交地址就是原地址 我们可以通过请求方式getpost 进行逻辑判断
1.6.1配置setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',#添加app01的应用
]
1.6.2配置配置url
from app01 import views
urlpatterns = [#只做路径匹配 不分post还是get
url(r'^admin/', admin.site.urls),
url(r'^login/', views.login),
url(r'^login/(d+)/(d+)/', views.articles), #articles/2019/9/
]
# 有名分组参数
url(r'^articles/(?P<month>d+)/(?P<year>d+)/', views.articles), #articles/2019/9/
#xx=2019 oo=9 关键字传参
1.6.3找到视图views.py写逻辑
request形参 对象 约定俗成
HttpResponse可以返回字符串
redirect重定向
from django.shortcuts import render,HttpResponse
print(request.path)
def login(request):
if request.method == 'POST':
name = request.POST.get('username') # 获取的是字符串用户输入的值
pwd = request.POST.get('pwd')
# print(name,pwd,'----------------------')
if name == 'aa' and pwd == 'aa':
return render(request, 'login2.html')
else:
return HttpResponse('登录失败!!')
else:
return render(request, 'login.html')#模板渲染 模板就是html页面 渲染就是字符串替换 第一个参数:request 第二个参数是html页面路径,
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def home(request):
return redirect(reverse('cs1'))
1.6.4创建login.html
如果action里面不写还是原页面 我们可以设置method进行逻辑判断
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<form action="" method="post"> <!-- http://127.0.0.1:8000 /login/ /login2/-->
用户名:<input type="text" name="username"> <!-- http://127.0.0.1:8000/login/login2/ -->
密码:<input type="text" name="pwd">
<input type="submit">
</form>
</body>
{#<script src="jquery.js"></script>#}
</html>
2 Django基础二之URL路由系统
2.1HTTP协议
详细https://www.cnblogs.com/clschao/articles/9230431.html
http协议
请求信息格式
GET / HTTP/1.1 请求行
Host: 127.0.0.1:8003 请求头
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
#空行
请求数据 username=ziwen password=666
get请求 请求数据部分是没有数据的,get请求的数据在url上,在请求行里面,有大小限制,常见的get请求方式: 浏览器输入网址,a标签
post请求 请求数据在请求体(请求数据部分) ,数据没有大小限制, 常见方式:form表单提交数据
2.2MVC和MTV框架模式
MVC:
M -- models 数据库相关
V -- views 视图相关(逻辑)
C -- controller url控制器(url分发器,路由分发)
django -- MTV
M -- models 数据库相关
T -- templates HTML相关 html就是模板
V -- views 视图相关(逻辑)
+ controller url控制器(url分发器,路由分发)
django下载安装
下载
pip3 install django==1.11.9
pip3 install django==1.11.9 -i http://xxxxxx 指定源
创建项目
django-admin startproject mysite 创建了一个名为"mysite"的Django 项目
启动项目
python manage.py runserver 默认是127.0.0.1:8000
python manage.py runserver 127.0.0.1 默认端口号是8000
python manage.py runserver 127.0.0.1:8001
2.3django的url路由分发
# url(r'^articles/(d+)/(d+)/', views.articles), #articles/2019/9/
视图函数
def articles(request,year,month): # 位置参数 2019 9
print(year,type(year)) #2019 <class 'str'> #匹配出来的所有数据都是字符串
print(month)
return HttpResponse(year+'年'+ month +'月' +'所有文章')
# 有名分组参数
url(r'^articles/(?P<xx>d+)/(?P<oo>d+)/', views.articles), #articles/2019/9/
#xx=2019 oo=9 关键字传参
def articles(request,oo,xx): # 关键字传参 2019 9
print(xx,type(xx)) #2019 <class 'str'> #匹配出来的所有数据都是字符串
print(oo)
return HttpResponse(xx+'年'+ oo +'月' +'所有文章')
3 Django基础三之视图函数
3.1视图
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了
HTTPRequest对象就是咱们的视图函数的参数request
# print(request) #<WSGIRequest: GET '/home/'>
# # print(dir(request))
#
# print(request.path) #/home/ 纯路径
# print(request.path_info) #/home/ 纯路径
# print(request.get_full_path()) #/home/?a=1&b=2 全路径(不包含ip地址和端口)
# print(request.META) #请求头相关数据,是一个字典
# print(request.method) #GET
# print(request.GET)
# print(request.POST)
# print(request.body) 能够拿到请求数据部分的数据(post,get没有)
HTTPResponse对象
HTTPResponse('字符串')
render(request,'xx.html')
redirect 重定向#用法 redirect(路径) 示例:redirect('/index/')
3.2FBV和CBV 视图
3.2.1FBV(函数类)
FBV(function base views) 就是在视图里使用函数处理请求。
from django.shortcuts import render,HttpResponse,redirect
def cs(request):
return redirect('/cs1/') #重定向 redirect(路径)
3.2.2CBV(对象)
CBV(class base views) 就是在视图里使用类处理请求。
最后一步源码
http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:#实现分发的
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
通过剖析源码 我们可以在分发前执行我们的逻辑
from django.views import View
class LoginView(View):
# def dispatch(self, request, *args, **kwargs):
# print('xx请求来啦!!!!')请求来之前 但不知道是什么方法前执行
# ret = super().dispatch(request, *args, **kwargs)
# print('请求处理的逻辑已经结束啦!!!')
# return ret
def get(self,request): #处理get请求直接定义get方法,不需要自己判断请求方法了,源码中用dispatch方法中使用了反射来处理的
print('小小小小')
return render(request,'login.html')
def post(self,request):
print(request.POST)
return HttpResponse('登录成功')
urls.py路由写法
url(r'^login/', views.LoginView.as_view()),
3.3视图类 加装饰器
3.3.1装饰器装饰FBV
FBV本身就是一个函数,所以和给普通的函数加装饰器无差
def wrapper(func):
def inner(*args, **kwargs):
start_time = time.time()
ret = func(*args, **kwargs)
end_time = time.time()
print("used:", end_time-start_time)
return ret
return inner
# FBV版添加班级
@wrapper
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
3.3.2装饰器装饰CBV
类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
第一步先引入模块from django.utils.decorators import method_decorator`
第2步 加语法糖@method_decorator(wrapper)`
from django.shortcuts import render,HttpResponse
from django.views import View
from django.utils.decorators import method_decorator
def wrapper(func):
def inner(*args, **kwargs):
print(11111)
ret = func(*args, **kwargs)
print(22222)
return ret
return inner
# @method_decorator(wrapper,name='get') # 方式3给get加 用的不多
class LoginView(View):
@method_decorator(wrapper) #方式1
def get(self,request):
print('小小小小')
return HttpResponse('登录成功')
def post(self,request):
print(request.POST)
return HttpResponse('登录成功')
3.4request对象
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
请求相关的常用值
- path_info 返回用户访问url,不包括域名
- method 请求中使用的HTTP方法的字符串表示,全大写表示。
- GET 包含所有HTTP GET参数的类字典对象
- POST 包含所有HTTP POST参数的类字典对象
- body 请求体,byte类型 request.POST的数据就是从body里面提取到的
属性
当get请求输入网址http://127.0.0.1:8000/cs/??a=1&b=2
def cs(request):
print(request) #<WSGIRequest: GET '/cs/??a=1&b=2'>
print(request.path) #/cs/ 纯路径
print(request.path_info) #/cs/ 纯路径
print(request.get_full_path())#/cs/??a=1&b=2全路径 (不包含ip地址和端口)
print(request.META) #请求头相关数据,是一个字典
print(request.method) #GET
print(request.GET)#<QueryDict: {'?a': ['1'], 'b': ['2']}>
print(request.POST)#<QueryDict: {}>
print(request.body) #能够拿到请求数据部分的数据(post,get没有) b''
return HttpResponse('666')
输入网址http://127.0.0.1:8000/cs/
def cs(request):
print(request) #<WSGIRequest: GET '/cs/??a=1&b=2'>
print(request.path) #/cs/ 纯路径
print(request.path_info) #/cs/ 纯路径
print(request.get_full_path())#/cs/??a=1&b=2全路径 (不包含ip地址和端口)
print(request.META) #请求头相关数据,是一个字典
print(request.method) #POST
print(request.GET)#<QueryDict: {}>
print(request.POST)#<QueryDict: {'a': ['1'], 'b': ['2']}>
print(request.body) # b'a=1&b=2' 能够拿到请求数据部分的数据(post,get没有)
return render(request,'cs.html')
a框输入1 b框输入2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
a<input type="text" name="a">
b<input type="text" name="b">
<input type="submit">
</form>
</body>
</html>
3.5Response对象
from django.shortcuts import render,HttpResponse,redirect
HTTPResponse('字符串') #返回字符串
render(request,'xx.html')#返回html页面
redirect 重定向
def cs(request):
return redirect('/cs1/') #重定向 redirect(路径)
def cs1(request):
return HttpResponse('666')
4 Django基础四之模板系统
4.1模板渲染的语法
模板渲染的官方文档
关于模板渲染你只需要记两种特殊符号(语法):
{{ }}和 {% %}
变量相关的用{{}},逻辑相关的用{%%}。
{{ 变量 }} {% 逻辑 %} -- 标签
4.2变量
在Django的模板语言中按此语法使用:{{ 变量名 }}。
当模版引擎遇到一个变量,它将计算这个变量,然后用结果替换掉它本身。 变量的命名包括任何字母数字以及下划线 ("_")的组合。 变量名称中不能有空格或标点符号。
我们可以利用 深度查询据点符(.)进行查询
4.2.1万能的点获取值
views.py视图函数中写法
from django.shortcuts import render
def home(request):
import datetime
current_time = datetime.datetime.now()
name = '小白'
num = 101
d1 = {'xx':'oo','xx2':'oo2','xx3':[11,22,33]}
d2 = ['11','22','33']
d3 = []
l1 = ['李业','陈硕','王洋','海狗']
class Person:
n = '类的属性'
def p(self):
return '类p的返回值'
obj = Person()
return render(request,'home.html',{'name':name,'d1':d1})
HTML页面写法
注意字典 列表 和对象中方法
<h2>{{ name }}</h2>
<h2>{{ d1.items }}</h2>items keys vlues
<h2>我是"{{ l1.1 }}"</h2>
<h2>{{ num }}</h2>
<h2>{{ obj.p }}</h2> #如果调用的方法需要传参,sorry用不了
4.3过滤器(内置)
过滤器的语法: {{ value|filter_name:参数 }}
使用管道符"|"来应用过滤器。
注意事项:
过滤器支持“链式”操作。即一个过滤器的输出作为另一个过滤器的输入。
过滤器可以接受参数,例如:{{ sss|truncatewords:30 }},这将显示sss的前30个词。
过滤器参数包含空格的话,必须用引号包裹起来。比如使用逗号和空格去连接一个列表中的元素,如:{{ list|join:‘, ‘ }}
‘|‘左右没有空格没有空格没有空格
参考博客:https://www.cnblogs.com/clschao/articles/10414811.html
default 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值。
{{ value|default:"nothing"}}
如果value没有传值或者值为空的话就显示nothing
length返回值的长度,作用于字符串和列表。
{{ value|length }}
返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
filesizeformat将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。
{{ value|filesizeformat }}
如果 value 是 123456789,输出将会是 117.7 MB。
slice
切片,如果 value="hello world",还有其他可切片的数据类型
{{value|slice:"2:-1"}}
date格式化,
value=datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s"}}
关于时间日期的可用的参数(除了Y,m,d等等)还有很多,有兴趣的可以去查查看看。
safe
{{ value|safe}}
如果value = "<a href='#'>点我</a>" 那么页面显示的是a标签
truncatechars如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
{{ value|truncatechars:9}} #注意:最后那三个省略号也是9个字符里面的,也就是这个9截断出来的是6个字符+3个省略号,有人会说,怎么展开啊,配合前端的点击事件就行啦
truncatewords在一定数量的字后截断字符串,是截多少个单词。
例如:‘hello girl hi baby yue ma’,
{{ value|truncatewords:3}} #上面例子得到的结果是 'hello girl h1...'
cut移除value中所有的与给出的变量相同的字符串
{{ value|cut:' ' }}
如果value为'i love you',那么将输出'iloveyou'.
join使用字符串连接列表,{{ list|join:', ' }},就像Python的str.join(list)
4.4标签Tags
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:
格式 {% tag %}
标签 内容 ... {% endtag %}
4.4.1for标签
{% for person in person_list %}
<p>{{ person.name }}</p> <!--凡是变量都要用两个大括号括起来-->
{% endfor %}
反向循环
{% for obj in list reversed %}
遍历一个字典:
{% for key,val in dic.items %}
<p>{{ key }}:{{ val }}</p>
{% endfor %}
forloop
forloop.counter 当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
实列
{% for i in d2 %}
{% for k,v in d1.items %}
<li>{{ forloop.counter }}-- {{ forloop.parentloop.counter }} === {{ k }} -- {{ v }}</li>
{% endfor %}
{% endfor %}
4.4.2for ... empty
for
标签带有一个可选的{% empty %}
从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
{% for person in person_list %}
<p>{{ person.name }}</p>
{% empty %}
<p>sorry,no person here</p>
{% endfor %}
4.4.3if 标签
{% if %}
会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
{% if num > 100 or num < 0 %}
<p>无效</p> <!--不满足条件,不会生成这个标签-->
{% elif num > 80 and num < 100 %}
<p>优秀</p>
{% else %} <!--也是在if标签结构里面的-->
<p>凑活吧</p>
{% endif %}
if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
4.4.4with
多用于给一个复杂的变量起别名,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
方法1
{% with total=business.employees.count %} #注意等号两边不能有空格
{{ total }} <!--只能在with语句体内用-->
{% endwith %}
方法2
{% with business.employees.count as total %}
{{ total }}
{% endwith %}
4.4.5csrf_token
安全认证机制
我们以post方式提交表单的时候,会报错,还记得我们在settings里面的中间件配置里面把一个csrf的防御机制给注销了啊,本身不应该注销的,而是应该学会怎么使用它,并且不让自己的操作被forbiden,通过这个东西就能搞定。
这个标签用于跨站请求伪造保护,
在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,因为后台我们django也存着这个东西,和你这个值相同的一个值,可以做对应验证是不是我给你的token,存储这个值的东西我们后面再学,你先知道一下就行了,就像一个我们后台给这个用户的一个通行证,如果你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登陆页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击我的网站,以后将中间件的时候我们在细说这个东西,但是现在你要明白怎么回事,明白为什么django会加这一套防御。
处理反扒
先get请求拿到<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,
name与values 在去请求
注意事项
- Django的模板语言不支持连续判断,即不支持以下写法:
{% if a > b > c %}
...
{% endif %}
4.5模板继承
4.5.1为什么要模板基础?
在写html页面中 发现有很多页面有雷同的样式 为了不必重复造轮子
Web框架需要一种很便利的方法用于动态生成HTML页面。 最常见的做法是使用模板。
模板包含所需HTML页面的静态部分,以及一些特殊的模版语法,用于将动态内容插入静态部分。
模板的设计实现了业务逻辑view与显示内容template的分离,一个视图可以使用任意一个模板,一个模板可以供多个视图使用。
4.5.2模板继承怎么实现?
1. 创建一个xx.html页面(作为母版,其他页面来继承它使用)
2. 在母版中定义block块(可以定义多个,整个页面任意位置)
{% block content %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
{% endblock %}
3 其他页面继承写法
{% extends 'base.html' %} 必须放在页面开头
4 页面中写和母版中名字相同的block块,从而来显示自定义的内容
{% block content %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
{{ block.super }} #这是显示继承的母版中的content这个快中的内容
这是xx1
{% endblock %}
以下是具体运行代码
4.5.2.1创建一个母模板
在templates文件夹 中创建一个muban.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板</title>
<style>
{% block css %}
#mub{
width: 100%;
height: 50px;
background-color: cornflowerblue;
}
{% endblock %}{#预留的钩子,共其他需要继承它的html,自定义自己的内容#}
</style>
</head>
<body>
<div id="mub">我是模板</div>
{% block content %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
<h1>我是模板h1</h1>
{% endblock %}
{% block cs2 %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
<h1>我是测试2</h1>
{% endblock %}
</body>
</html>
4.5.2.2其他页面继承写法
在templates文件夹 中创建一个home.html 继承于muban.html
{% extends 'muban.html' %}
{% block css %}
#mub{
width: 100%;
height: 50px;
background-color: red;
}
#s6{
width: 50%;
height: 50px;
background-color: red;
float: right;
}
{% endblock %}
{% block content %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
<h1>我改变了模板的内容</h1>
<div id="s6">我来测试</div>
{% endblock %}
{% block cs2 %} <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
{{ block.super }}
我在测试2下面
{% endblock %}
4.6组件
组件就是类似于python中的模块 什么时候用 什么时候导入 比如常见的导航条,页尾信息等组件 我们一般 保存在单独的文件中,
1 创建html页面,里面写上自己封装的组件内容,xx.html
2 新的html页面使用这个组件
{% include 'xx.html' %}
以下是代码
4.6.1创建组件
在templates文件夹 中创建一个组件 title.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.nav{
background-color: pink;
height: 40px;
}
</style>
</head>
<body>
<div class="nav">
<span>个人中心</span>
<span>首页</span>
<span>注册</span>
<span>登录</span>
</div>
</body>
</html>
4.6.2引用组件
在templates文件夹 中创建一个home.html 引用组件 title.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% include 'title.html' %}
<h1>这是新项目首页</h1>
</body>
</html>
4.7自定义标签和过滤器
4.7.1为什么要有自定义标签和过滤器?
因为在现实编程中可能内置的标签过滤器 不可以满足我们的需求 所有需要我们自己来创建
4.7.2创建自定义标签和过滤器的流程
1 在应用下创建一个叫做templatetags的文件夹(名称不能改),在里面创建一个py文件,例如xx.py
2 在xx.py文件中引用django提供的template类,写法
from django import template
register = template.Library() #register变量名称不能改
定义过滤器
@register.filter 参数至多两个
def xx(v1,v2):
return xxx
使用:
{% load xx %} xx是py文件
{{ name|xx:'oo' }}
# 自定义标签 没有参数个数限制
from django import template
register = template.Library() #register变量名称不能改
@register.filter #参数至多两个
def guolv(v1,v2):
"""
:param v1: 变量的值 管道前面的
:param v2: 传的参数 管道后面的,如果不需要传参,就不要添加这个参数
:return:
"""
return v1+v2
下面是执行的代码
4.7.2.1在应用文件夹下 创建templatetags文件夹并在里面创建一个xx.文件
from django import template
register = template.Library() #register变量名称不能改
@register.filter #参数至多两个
def guolv(v1,v2):
"""
:param v1: 变量的值 管道前面的
:param v2: 传的参数 管道后面的,如果不需要传参,就不要添加这个参数
:return:
"""
return v1+v2
4.7.2.2视图views中代码
from django.shortcuts import render,HttpResponse
name='测试+'
def home(request):
return render(request,'home.html',{'name':name})
4.7.2.3创建要引用自定义过滤器的html页面
{% load xx %}{#xx是templatetags文件夹下的xx.py文件#}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
{{ name|guolv:'要传给n2的参数' }}
</body>
</html>
4.7.3 inclusion_tag
多用于返回html代码片段
原理先运行nue.html 调用xx.py 中res函数
res函数将返回值给@register.inclusion_tag对应的页面(‘result.html‘) 模板渲染后 以组件的形式给原来的nue.htm
nue.htm
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% res a %}#a是参数
</body>
</html>
result.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>
{% for i in li %}
<li>{{ i }}</li>
{% endfor %}
</ul>
</body>
</html>
xx.py
# inclusion_tag 返回html片段的标签
@register.inclusion_tag('result.html')
def res(n1): #n1 : ['aa','bb','cc']
return {'li':n1 }
4.8静态文件相关
4.8.1静态文件配置
js、css、img等都叫做静态文件,那么关于django中静态文件的配置,我们就需要在settings配置文件里面写上这写内容:
目录:别名也是一种安全机制,浏览器上通过调试台你能够看到的是别名的名字,这样别人就不能知道你静态文件夹的名字了,不然别人就能通过这个文件夹路径进行攻击。
1 项目目录下创建一个文件夹,例如名为static_file,将所有静态文件放到这个文件夹中
2 settings 配置文件中进行下面的配置
# 静态文件相关配置
STATIC_URL = '/abc/' #静态文件路径别名
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'jingtaiwenjianjia'),
]
{% load static %}
3 引入<link rel="stylesheet" href="/abc/css/index.css">
4.8.1.1项目目录下创建一个文件夹,例如名为static_file,将所有静态文件放到这个文件夹中
4.8.1.2 找到settings 配置文件中进行下面的配置
STATIC_URL = '/abc/' #静态文件路径别名 可以随便改
#注意第2个参数一定对应创建的文件夹名 别名可以随便改
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_file'),
]
4.8.1.3引入的配置文件的html页面内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/abc/css/index.css">
<link rel="stylesheet" href="/abc/plugins/bootstrap-3.3.7-dist/css/bootstrap.min.css">
</head>
<body>
<input type="text" class="form-control">
<h1>红浪漫spa会所</h1>
<img src="/abc/img/timg.jpg" alt="">
<a href="{% url 'home' %}">首页</a>
技师:
<ul>
<li>小白</li>
<li>小黑</li>
</ul>
</body>
</html>
4.8.2url别名和反向解析
我们给url 起一个别名· 以后不管url怎么改 都可以实现原来的网址 就不会写死了
rurl文件写法
url(r'^index2/', views.index,name='cs'),
反向解析
后端views: from django.urls import reverse 可以实现反向解析
reverse('别名') 例如:reverse('cs') 反向解析为别名对应的地址 /index2/
带参数的反向解析: reverse( index' ,args=(10,))--- /index2/10/
html: {% url '别名' %} -- 例如:{% url 'cs' %} -- /index2/
下面是代码
rurl文件写法
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^cs/', views.home,name='cs'),
url(r'^cs1/', views.cs1,name='cs1'),
]
后端views.py
用于重定向 redirect
我们利用别名 以后不管 别名cs1 对应的网址这么变 我们通过反解析 ,都可以找到他,写活了他
from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def home(request):
return redirect(reverse('cs1'))
def cs1(request):
return HttpResponse('测试')
4.8.3url命名空间
在路由分发中可能会错乱为了 避免
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
# url(r'^admin/', admin.site.urls),
url(r'^app01/', include('app01.urls',namespace='app01')),#app01/home/
url(r'^app02/', include('app02.urls',namespace='app02')),
]
使用:
后端:reverse('命名空间名称:别名') -- reverse('app01:home')
hmtl:{% url '命名空间名称:别名' %} -- {% url 'app01:home' %}
5 orm单表操作
orm语句 -- sql -- 调用pymysql客户端发送sql -- mysql服务端接收到指令并执行
5.1ORM简介
- MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
- ORM是“对象-关系-映射”的简称。(Object Relational Mapping,简称ORM)(将来会学一个sqlalchemy,是和他很像的,但是django的orm没有独立出来让别人去使用,虽然功能比sqlalchemy更强大,但是别人用不了)
- 类对象--->sql--->pymysql--->mysql服务端--->磁盘,orm其实就是将类对象的语法翻译成sql语句的一个引擎,明白orm是什么了,剩下的就是怎么使用orm,怎么来写类对象关系语句。
5.2单表操作
5.2.1创建表
注意创建表前 必须先手动在数据库 中创建一个库 并配好setting中配置
第一步在应用文件夹下 models.py文件中创建一个类
字段与参数 详见5.2.1
class Csbiao(models.Model):#Csbiao创建的表名
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=10)
birthday=models.DateField()
checked = models.BooleanField()
4 执行数据库同步指令,添加字段的时候别忘了,该字段不能为空,所有要么给默认值,要么设置它允许为空null=True
在 Terminal中执行
python manage.py makemigrations #生成记录,每次修改了models里面的内容或者添加了新的app,新的app里面写了models里面的内容,都要执行这两条
python manage.py migrate #执行上面这个语句的记录来创建表,生成的表名字前面会自带应用的名字,例如:你的book表在mysql里面叫做app01_book表
5.2.1 settings配置
settings配置文件中
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',#固定的
'NAME': 'cs',#cs是数据库中的库
'USER':'root',#账号
'PASSWORD':'',#密码
'HOST':'127.0.0.1',#ip地址
'PORT':3306,#端口号
}
}
2 项目文件夹下的init文件中写上下面内容,用pymysql替换mysqldb
import pymysql
pymysql.install_as_MySQLdb()
settings配置文件中将USE_TZ的值改为False
# USE_TZ = True
USE_TZ = False # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
使用pycharm的数据库客户端的时候,时区问题要注意
5.2.1 更多字段和参数
<1> CharField
字符串字段, 用于较短的字符串.
CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
<2> IntegerField
#用于保存一个整数.
<3> DecimalField
一个浮点数. 必须 提供两个参数:
参数 描述
max_digits 总位数(不包括小数点和符号)
decimal_places 小数位数
举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
models.DecimalField(..., max_digits=5, decimal_places=2)
要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
models.DecimalField(..., max_digits=17, decimal_places=10) #max_digits大于等于17就能存储百万以上的数了
admin 用一个文本框(<input type="text">)表示该字段保存的数据.
<4> AutoField
一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段;
自定义一个主键:my_id=models.AutoField(primary_key=True)
如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
<5> BooleanField bool字段
A true/false field. admin 用 checkbox 来表示此类字段.
<6> TextField
一个容量很大的文本字段.
admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
<7> EmailField
一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
<8> DateField
一个日期字段. 共有下列额外的可选参数:
Argument 描述
auto_now 当对象被保存时(更新或者添加都行),自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
auto_now_add 当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
(仅仅在admin中有意义...)
<9> DateTimeField
一个日期时间字段. 类似 DateField 支持同样的附加选项.
<10> ImageField 图片·
类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
如果提供这两个参数,则图片将按提供的高度和宽度规格保存.
<11> FileField 文件
一个文件上传字段.
要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting,
该格式将被上载文件的 date/time
替换(so that uploaded files don't fill up the given directory).
admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件.
(出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对
WEB服务器用户帐号是可写的.
(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT).
出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField
叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
<12> URLField
用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
没有返回404响应).
admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
<13> NullBooleanField
类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes" 和 "No" ) 来表示这种字段数据.
<14> SlugField
"Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50. #在
以前的 Django 版本,没有任何办法改变50 这个长度.
这暗示了 db_index=True.
它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate
the slug, via JavaScript,in the object's admin form: models.SlugField
(prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
<13> XMLField
一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
<14> FilePathField
可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
参数 描述
path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目.
Example: "/home/images".
match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.
注意这个正则表达式只会应用到 base filename 而不是
路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
这三个参数可以同时使用.
match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
FilePathField(path="/home/images", match="foo.*", recursive=True)
...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
<15> IPAddressField
一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16> CommaSeparatedIntegerField
用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
更多参数
1)null
如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
(1)blank
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
(2)default
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
(3)primary_key
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。
(4)unique
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
(5)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
(6)db_index
如果db_index=True 则代表着为此字段设置数据库索引。
DatetimeField、DateField、TimeField这个三个时间字段,都可以设置如下属性。
(7)auto_now_add
配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
(8)auto_now
配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
5.2.1自定义字段(了解)
5.2.2添加表纪录
第一步views表引入app01文件夹下的models.py文件from app01 import models
方式1:
new_obj=models.Csbiao(#Csbiao类名也是表名
name='cs',
birthday='2019-09-27',
checked=1,
)
new_obj.save()
方式2:
ret = models.Csbiao.objects.create(
name='cs111',
birthday='2019-09-27',
checked=1,
)
# ret 是创建的新的记录的model对象(重点)
print(ret) #UserInfo object 卫贺
print(ret.name) #UserInfo object
print(ret.bday) #UserInfo object
5.2.2.1 时间问题
models.UserInfo.objects.create(
name='杨泽涛2',
bday=current_date,
# now=current_date, 直接插入时间没有时区问题
checked=0
)
但是如果让这个字段自动来插入时间,就会有时区的问题,auto_now_add创建记录时自动添加当前创建记录时的时间,存在时区问题
now = models.DateTimeField(auto_now_add=True,null=True)
解决方法:
settings配置文件中将USE_TZ的值改为False
# USE_TZ = True
USE_TZ = False # 告诉mysql存储时间时按照当地时间来寸,不要用utc时间
使用pycharm的数据库客户端的时候,时区问题要注意
5.2.3查询表纪录
<1> all(): 查询所有结果,结果是queryset类型
查询所有的数据 .all方法 返回的是queryset集合
all_objs = models.Student.objects.all() # 类似于列表 -- queryset集合
# for i in all_objs:
# print(i.name)
print(all_objs)
<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象,结果也是queryset类型 Book.objects.filter(title='linux',price=100) #里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的我们后面再学,直接在这里写是搞不定or的
models.Student.objects.filter(id=7,name='大壮哥哥',age=78).update(
name='大壮禅师',
age=78
)
#打散形式传参
models.Student.objects.filter(**{'id':7,'name':'大壮禅师'}).update(age=100)
models.Student.objects.all().filter(id=7) queryset类型可以调用fitler在过滤
<3> get(**kwargs): 返回与所给筛选条件相匹配的对象,不是queryset类型,是行记录对象,返回结果有且只有一个,
如果符合筛选条件的对象超过一个或者没有都会抛出错误。捕获异常try。 Book.objects.get(id=1)
<4> exclude(**kwargs): 排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 Book.objects.exclude(id=6),返回id不等于6的所有的对象,或者在queryset基础上调用,Book.objects.all().exclude(id=6)
exclude(**kwargs): 排除,objects控制器和queryset集合都可以调用,返回结果是queryset类型
query = models.Student.objects.exclude(id=1)
print(query)
query = models.Student.objects.filter(age=38).exclude(id=6)
print(query)
<5> order_by(*field): 排序 queryset类型的数据来调用,对查询结果排序,默认是按照id来升序排列的,返回值还是queryset类型
models.Book.objects.all().order_by('price','id') #直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by('-cs'),order_by('price','id')是多条件排序,按照price进行升序,price相同的数据,按照id进行升序
<6> reverse(): queryset类型的数据来调用,对查询结果反向排序,返回值还是queryset类型
# 只可以排序之后反转
# query = models.Student.objects.all().order_by('id').reverse()
# print(query)
<7> count(): queryset类型的数据来调用,返回数据库中匹配查询(QuerySet)的对象数量。
<8> first(): queryset类型的数据来调用,返回第一条记录 Book值
<9> last(): queryset类型的数据来调用,返回最后一条记录,结果为model对象类型
<10> exists(): queryset类型的数据来调用,如果QuerySet包含数据,就返回True,否则返回False
空的queryset类型数据也有布尔值True和False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,你用它来判断,那么就需要查询出所有的数据,效率太差了,用count或者exits
例:all_books = models.Book.objects.all().exists() #翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据
<11> values(*field): 用的比较多,queryset类型的数据来调用,返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列
model的实例化对象,而是一个可迭代的字典序列,只要是返回的queryset类型,就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。 里面可以加子段显示
<12> values_list(*field): 它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 里面可以加子段显示
<13> distinct(): values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录 去重,结果还是queryset 里面不可以传参 显示nanme等等可以用来去重
query = models.Student.objects.all().values('age').distinct()
print(query)
5.2.3.2基于双下划线的模糊查询
Book.objects.filter(price__in=[100,200,300]) #price值等于这三个里面的任意一个的对象
Book.objects.filter(price__gt=100) #大于,大于等于是price__gte=100,别写price>100,这种参数不支持
Book.objects.filter(price__lt=100) 小于
Book.objects.filter(price__range=[100,200]) #sql的between and,大于等于100,小于等于200
Book.objects.filter(title__contains="python") #title值中包含python的
Book.objects.filter(title__icontains="python") #不区分大小写
Book.objects.filter(title__startswith="py") #以什么开头,istartswith 不区分大小写
Book.objects.filter(pub_date__year=2012) date类型
# all_books = models.Book.objects.filter(pub_date__year=2012) #找2012年的所有书籍
# all_books = models.Book.objects.filter(pub_date__year__gt=2012)#找大于2012年的所有书籍
all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)#找2019年月份的所有书籍,如果明明有结果,你却查不出结果,是因为mysql数据库的时区和咱们django的时区不同导致的,了解一下就行了,你需要做的就是将django中的settings配置文件里面的USE_TZ = True改为False,就可以查到结果了,以后这个值就改为False,而且就是因为咱们用的mysql数据库才会有这个问题,其他数据库没有这个问题。
5.2.4删除表纪录
简单查询:filter() -- 结果是queryset类型的数据里面是一个个的model对象,类似于列表
models.UserInfo.objects.filter(id=7).delete() #queryset对象调用
models.UserInfo.objects.filter(id=7)[0].delete() #model对象调用
5.2.5修改表纪录
方式1:update
models.UserInfo.objects.filter(id=2).update(
name='篮子文',
checked = 0,
)
#错误示例,model对象不能调用update方法
models.UserInfo.objects.filter(id=2)[0].update(
name='加篮子+2',
# checked = 0,
)
方式2
ret = models.UserInfo.objects.filter(id=2)[0]
ret.name = '加篮子+2'
ret.checked = 1
ret.save()
更新时的auto_now参数
# 更新记录时,自动更新时间,创建新纪录时也会帮你自动添加创建时的时间,但是在更新时只有使用save方法的方式2的形式更新才能自动更新时间,有缺陷,放弃
now2 = models.DateTimeField(auto_now=True,null=True)
以上是关于python之Django的主要内容,如果未能解决你的问题,请参考以下文章
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE的解决办法(转)(代码片段
如何在 Django Summernote 中显示编程片段的代码块?