一 什么是web框架?
框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。
对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端
import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK ".encode("utf8")) client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。
这个接口就是WSGI:Web Server Gateway Interface。
-----------------------------模拟框架实现功能---------------------------
所需的HTML代码自行添加 from wsgiref.simple_server import make_server import time def yhr(req): f = open("index2.html","rb") data = f.read() return data def login(req): print(req["QUERY_STRING"]) return b"welcome !" def singup(req): pass def show_time(req): times =time.ctime() # return ("<h1>time:%s</h1>"%str(times)).encode("utf8") f = open("show_time.html","rb") data = f.read() data = data.decode("utf8") data = data.replace("{{time}}",str(times)) return data.encode("utf8") def router(): url_patterns = [ ("/login",login), ("/singup",singup), ("/yhr",yhr), ("/show_time",show_time) ] return url_patterns def application(environ, start_response): print("path",environ["PATH_INFO"]) path = environ["PATH_INFO"] # 取数据 start_response('200 OK', [('Content-Type', 'text/html')]) url_patterns = router() func = None for item in url_patterns: if item[0] == path: func = item[1] break if func: return [func(environ)] else: return [b"404"] httpd = make_server('', 8000, application) print('Serving HTTP on port 8000...') # 开始监听HTTP请求: httpd.serve_forever()
二 MVC和MTV模式
著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。
模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
三 django的流程和命令行工具
django实现流程
django #安装: pip3 install django 添加环境变量 :在安装Python3的lib---》site.packages---》django---》bin #1 创建project django-admin startproject mysite ---mysite ---settings.py ---url.py ---wsgi.py ---- manage.py(启动文件) #2 创建APP python mannage.py startapp app01 #3 settings配置 TEMPLATES STATICFILES_DIRS=( os.path.join(BASE_DIR,"statics"), ) STATIC_URL = '/static/' # 我们只能用 STATIC_URL,但STATIC_URL会按着你的STATICFILES_DIRS去找#4 根据需求设计代码 url.py view.py #5 使用模版 render(req,"index.html") #6 启动项目 python manage.py runserver 127.0.0.1:8090 #7 连接数据库,操作数据 model.py
django的命令行工具
django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每一个Django Project里都会有一个mannage.py。
<1> 创建一个django工程 : django-admin.py startproject mysite
当前目录下会生成mysite的工程,目录结构如下:
- manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
- settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
- urls.py ----- 负责把URL模式映射到应用程序。
<2>在mysite目录下创建blog应用: python manage.py startapp blog
<3>启动django项目:python manage.py runserver 8080
这样我们的django就启动起来了!当我们访问:http://127.0.0.1:8080/时就可以看到:
<4>生成同步数据库的脚本:python manage.py makemigrations
同步数据库: python manage.py migrate
注意:在开发过程中,数据库同步误操作之后,难免会遇到后面不能同步成功的情况,解决这个问题的一个简单粗暴方法是把migrations目录下
的脚本(除__init__.py之外)全部删掉,再把数据库删掉之后创建一个新的数据库,数据库同步操作再重新做一遍。
<5>当我们访问http://127.0.0.1:8080/admin/时,会出现:
所以我们需要为进入这个项目的后台创建超级管理员:python manage.py createsuperuser,设置好用户名和密码后便可登录啦!
<6>清空数据库:python manage.py flush
<7>查询某个命令的详细信息: django-admin.py help startapp
admin 是Django 自带的一个后台数据库管理系统。
<8>启动交互界面 :python manage.py shell
这个命令和直接运行 python 进入 shell 的区别是:你可以在这个 shell 里面调用当前项目的 models.py 中的 API,对于操作数据,还有一些小测试非常方便。
<9> 终端上输入python manage.py 可以看到详细的列表,在忘记子名称的时候特别有用。
四 Django的配置文件(settings)
1 一、概述: 2 3 #静态文件交由Web服务器处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例): 4 5 # URI请求-----> 按照Web服务器里面的配置规则先处理,以nginx为例,主要求配置在nginx. 6 #conf里的location 7 8 |---------->如果是静态文件,则由nginx直接处理 9 10 |---------->如果不是则交由Django处理,Django根据urls.py里面的规则进行匹配 11 12 # 以上是部署到Web服务器后的处理方式,为了便于开发,Django提供了在开发环境的对静态文件的处理机制,方法是这样: 13 14 #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles', 15 16 #2、在urls.py里面加入 17 if settings.DEBUG: 18 urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 19 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }), 20 url(r'^static/(?P<path>.*)$', 21 'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), ) 22 23 # 3、这样就可以在开发阶段直接使用静态文件了。 24 25 二、MEDIA_ROOT和MEDIA_URL 26 27 #而静态文件的处理又包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的: 28 29 #MEDIA:指用户上传的文件,比如在Model里面的FileFIeld,ImageField上传的文件。如果你定义 30 31 #MEDIA_ROOT=c: empmedia,那么File=models.FileField(upload_to="abc/")#,上传的文件就会被保存到c: empmediaabc 32 #eg: 33 class blog(models.Model): 34 Title=models.charField(max_length=64) 35 Photo=models.ImageField(upload_to="photo") 36 # 上传的图片就上传到c: empmediaphoto,而在模板中要显示该文件,则在这样写 37 #在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写: 38 BASE_DIR= os.path.abspath(os.path.dirname(__file__)) 39 MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\','/') 40 41 #MEDIA_URL是指从浏览器访问时的地址前缀,举个例子: 42 MEDIA_ROOT=c: empmediaphoto 43 MEDIA_URL="/data/" 44 #在开发阶段,media的处理由django处理: 45 46 # 访问http://localhost/data/abc/a.png就是访问c: empmediaphotoabca.png 47 48 # 在模板里面这样写<img src="{{MEDIA_URL}}abc/a.png"> 49 50 # 在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置, 51 # 以便能让web服务器能访问media文件 52 # 以nginx为例,可以在nginx.conf里面这样: 53 54 location ~/media/{ 55 root/temp/ 56 break; 57 } 58 59 # 具体可以参考如何在nginx部署django的资料。 60 61 三、STATIC_ROOT和STATIC_URL、 62 STATIC主要指的是如css,js,images这样文件,在settings里面可以配置STATIC_ROOT和STATIC_URL, 63 配置方式与MEDIA_ROOT是一样的,但是要注意 64 65 #STATIC文件一般保存在以下位置: 66 67 #1、STATIC_ROOT:在settings里面设置,一般用来放一些公共的js,css,images等。 68 69 #2、app的static文件夹,在每个app所在文夹均可以建立一个static文件夹,然后当运行collectstatic时, 70 # Django会遍历INSTALL_APPS里面所有app的static文件夹,将里面所有的文件复制到STATIC_ROOT。因此, 71 # 如果你要建立可复用的app,那么你要将该app所需要的静态文件放在static文件夹中。 72 73 # 也就是说一个项目引用了很多app,那么这个项目所需要的css,images等静态文件是分散在各个app的static文件的,比 74 # 较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT。 75 76 #3、STATIC文件还可以配置STATICFILES_DIRS,指定额外的静态文件存储位置。 77 # STATIC_URL的含义与MEDIA_URL类似。 78 79 # ---------------------------------------------------------------------------- 80 #注意1: 81 #为了后端的更改不会影响前端的引入,避免造成前端大量修改 82 83 STATIC_URL = '/static/' #引用名 84 STATICFILES_DIRS = ( 85 os.path.join(BASE_DIR,"statics") #实际名 ,即实际文件夹的名字 86 ) 87 88 #django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找 89 #<script src="/statics/jquery-3.1.1.js"></script> 90 #------error-----不能直接用,必须用STATIC_URL = '/static/': 91 #<script src="/static/jquery-3.1.1.js"></script> 92 93 #注意2(statics文件夹写在不同的app下,静态文件的调用): 94 95 STATIC_URL = '/static/' 96 97 STATICFILES_DIRS=( 98 ('hello',os.path.join(BASE_DIR,"app01","statics")) , 99 ) 100 101 #<script src="/static/hello/jquery-1.8.2.min.js"></script> 102 103 #注意3: 104 STATIC_URL = '/static/' 105 {% load staticfiles %} 106 # <script src={% static "jquery-1.8.2.min.js" %}></script>
其它重要参数设置:
1 APPEND_SLASH 2 Default: True 3 When set to True, if the request URL does not match any of the patterns in the URLconf and it 4 doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note 5 that the redirect may cause any data submitted in a POST request to be lost.
五 Django URL (路由系统)
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。
urlpatterns = [ url(正则表达式, views视图函数,参数,别名), ]
参数说明:
- 一个正则表达式字符串
- 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
- 可选的要传递给视图函数的默认参数(字典形式)
- 一个可选的name参数
例如:url(r'student', views.student,{"time:t"},name="stu"),
5.1 这是一个示例URLconf
1 from django.conf.urls import url 2 from django.contrib import admin 3 4 from app01 import views 5 6 urlpatterns = [ 7 8 url(r'^articles/2003/$', views.special_case_2003), 9 10 #url(r'^articles/[0-9]{4}/$', views.year_archive), 11 12 url(r'^articles/([0-9]{4})/$', views.year_archive), #no_named group 13 14 url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), 15 16 url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), 17 18 ]
上面的例子中使用简单,non-named正则表达式组(通过括号)捕捉到的URL,将他们作为一个视图的位置参数。在更高级的用法,可以使用指定的正则表达式组捕获的URL部分并将它们作为关键字参数传递给一个视图。
在Python中正则表达式,指定的正则表达式的语法组(? P <名称>模式),在那里的名字是集团的名称和模式是模式匹配。
这是上面的例子URLconf,重写使用命名组:
1 import re 2 3 ret=re.search('(?P<id>d{3})/(?P<name>w{3})','weeew34ttt123/ooo') 4 5 print(ret.group()) 6 print(ret.group('id')) 7 print(ret.group('name'))
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^articles/2003/$', views.special_case_2003),
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]
这完成了前面的例子一样,有一个微妙的差异:捕获的值传递给视图函数作为关键字参数而不是位置参数。
5.3 通过额外的选项来查看功能
URLconfs有钩,允许您将额外的参数传递给视图功能,作为一个Python字典。
django.conf.urls.url()函数可以用一个可选的第三个参数应该字典的额外关键字参数传递到视图的功能。
例子:
from django.conf.urls import url from . import views urlpatterns = [ url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]
在本例中,请求/博客/ 2005 / Django将调用视图。year_archive(请求,年= ' 2005 ',foo = '酒吧')。
这种技术用于聚合框架通过元数据和视图选项。
处理冲突
可以有一个URL模式捕获关键字参数,并通过参数具有相同名字的字典的额外参数。当这种情况发生时,在字典里的参数将用来替代参数捕获的URL。
5.4 参数名称
URL urlpatterns = [ url(r'^index',views.index,name='bieming'), url(r'^admin/', admin.site.urls), # url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail), ] ################### views视图函数 def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登陆成功") return render(req,'index.html') ##################### templates里面的HTML <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# <form action="/index/" method="post">#} <form action="{% url 'bieming' %}" method="post"> 用户名:<input type="text" name="username"> 密码:<input type="password" name="password"> <input type="submit" value="submit"> </form> </body> </html> #######################
5.5 包括其他URLconfs
#At any point, your urlpatterns can “include” other URLconf modules. This #essentially “roots” a set of URLs below other ones. #For example, here’s an excerpt of the URLconf for the Django website itself. #It includes a number of other URLconfs: from django.conf.urls import include, url urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^blog/', include('blog.urls')), ]
六 Django Views(视图函数)
http请求中产生两个核心对象:
http请求:HttpRequest对象
http响应:HttpResponse对象
所在位置:django.http
之前我们用到的参数request就是HttpRequest 检测方法:isinstance(request,HttpRequest)
1 HttpRequest对象的属性和方法:
# path: 请求页面的全路径,不包括域名 # # method: 请求中使用的HTTP方法的字符串表示。全大写表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含所有HTTP GET参数的类字典对象 # # POST: 包含所有HTTP POST参数的类字典对象 # # 服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过 # HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用 # if request.POST来判断是否使用了HTTP POST 方法;应该使用 if request.method=="POST" # # # # COOKIES: 包含所有cookies的标准Python字典对象;keys和values都是字符串。 # # FILES: 包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />
标签中 name属性的值,FILES中的每一个value同时也是一个标准的python字典对象,包含下面三个Keys: # # filename: 上传文件名,用字符串表示 # content_type: 上传文件的Content Type # content: 上传文件的原始内容 # # # user: 是一个django.contrib.auth.models.User对象,代表当前登陆的用户。如果访问用户当前 # 没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你 # 可以通过user的is_authenticated()方法来辨别用户是否登陆: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 时该属性才可用 # # session: 唯一可读写的属性,代表当前会话的字典对象;自己有激活Django中的session支持时该属性才可用。 #方法 get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 req.path:/index33
注意一个常用方法:request.POST.getlist('') 如果传送后端的是列表要用POST.getlist()取值
2 HttpResponse对象:
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染: render(request,“HTML”)(推荐)<br> render_to_response(), 页面跳转: redirect("路径") locals(): 可以直接将函数中所有的变量传给模板
七 Template基础
模板系统介绍
模板系统的组成:HTML代码和逻辑控制代码
逻辑控制代码可以理解是django模板语言
django的模板语言组成
-
变量(使用双大括号来引用变量):
- 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)
- 模板继承
模板语言之变量
语法
1 {{var_name}} var_name 指变量名
------Template和Context对象
>>> python manange.py shell (进入该django项目的环境) >>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) 'My name is Stephane.' # 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以 # 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会 # 更为高效: # Low for name in ('John', 'Julie', 'Pat'): t = Template('Hello, {{ name }}') print t.render(Context({'name': name})) # Good t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'): print t.render(Context({'name': name}))
Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。
from django.shortcuts import render,HttpResponse from django.template.loader import get_template #记得导入 # Create your views here. import datetime from django.template import Template,Context # def current_time(req): #原始的视图函数 # now=datetime.datetime.now() # html="<html><body>现在时刻:<h1>%s.</h1></body></html>" %now # return HttpResponse(html) # def current_time(req): #django模板修改的视图函数 # now=datetime.datetime.now() # t=Template('<html><body>现在时刻是:<h1 style="color:red">{{current_date}}</h1></body></html>') #t=get_template('current_datetime.html') # c=Context({'current_date':now}) # html=t.render(c) # return HttpResponse(html) #另一种写法(推荐) def current_time(req): now=datetime.datetime.now() return render(req, 'current_datetime.html', {'current_date':now}) 推荐方式
------深度变量的查找(万能的句点号)
在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。
在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。
#最好是用几个例子来说明一下。 # 首先,句点可用于访问列表索引,例如: >>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) 'Item 2 is carrots.' #假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点: >>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'Sally is 43 years old.' #同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有 #year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性: >>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(1993, 5, 2) >>> d.year 1993 >>> d.month 5 >>> d.day 2 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') >>> c = Context({'date': d}) >>> t.render(c) 'The month is 5 and the year is 1993.' # 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适 # 用于任意的对象。 >>> from django.template import Template, Context >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name, self.last_name = first_name, last_name >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') >>> c = Context({'person': Person('John', 'Smith')}) >>> t.render(c) 'Hello, John Smith.' # 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit() # 方法,你在模板中可以使用同样的句点语法来调用它们: >>> from django.template import Template, Context >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') >>> t.render(Context({'var': 'hello'})) 'hello -- HELLO -- False' >>> t.render(Context({'var': '123'})) '123 -- 123 -- True' # 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的 # 方法。
变量的过滤器(filter)的使用
语法格式
{{var|filter:param}}
管道符号后面的功能,比如{{ var|length }},求变量长度的 length 就是一个过滤器。
常用的过滤器
1.add : 给变量加上相应的值 2 addslashes : 给变量中的引号前加上斜线 3 capfirst : 首字母大写 4 cut : 从字符串中移除指定的字符 5 date : 格式化日期字符串 6 default : 如果值是False,就替换成设置的默认值,否则就是用本来的值 7 default_if_none: 如果值是None,就替换成设置的默认值,否则就使用本来的值
标签(tag)的使用
语法格式
{% tags %}
{% if %} 的使用
{% if %} 和 {% endif %}要成对
{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容
{% if num >= 100 and 8 %} {% if num > 200 %} <p>num大于200</p> {% else %} <p>num大于100小于200</p> {% endif %} {% elif num < 100%} <p>num小于100</p> {% else %} <p>num等于100</p> {% endif %} {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量 {% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的: {% if obj1 and obj2 or obj3 %}
------{% for %}的使用
{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容
基本格式 <ul> {% for obj in list %} <li>{{ obj.name }}</li> {% endfor %} </ul
标签里添加reversed来反序循环列表:
{% for obj in list reversed %} ... {% endfor %}
{% for %}标签可以嵌套:
{% for country in countries %} <h1>{{ country.name }}</h1> <ul> {% for city in country.city_list %} <li>{{ city }}</li> {% endfor %} </ul> {% endfor %}
{% for %}不支持中断循环,也不支持continue语句
{% for %}关于循环其他用法
forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1: forloop.counter0 索引从 0 开始算 forloop.revcounter表示循环中剩下的items数量,第一次循环时设为items总数,最后一次设为1 forloop.revcounter0表示`items总数少一个,最后一次循环设置为0 forloop.first表示当第一次循环时值为True,在特别情况下很有用: forloop.last表示当最后一次循环时值为True forloop.parentioop表示在嵌套循环中表示父级循环的forloop
富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
Django会在for标签的块中覆盖你定义的forloop变量的值
在其他非循环的地方,你的forloop变量仍然可用
{% for item in todo_list %} <p>{{ forloop.counter }}: {{ item }}</p> {% endfor %} 表示循环的次数,它从1开始计数,第一次循环设为1:
{%csrf_token%}:csrf_token标签
用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效
{% url %}: 引用路由配置的地址
<form action="{% url "路由别名"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
{% with %}:用更简单的变量名替代复杂的变量名
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %} 基本很少起复杂变量名,一般起变量名都要特变形象
{% verbatim %}: 禁止render渲染
{% verbatim %} {{ hello }} {% endverbatim % 如果想要{{hello}}在网页正常显示出来,则用这个
{% load %}: 加载标签库
静态文件的引入方式用过
{% load staticfiles %}
后面引入其他的标签库在一一列出
自定义filter和simple_tag
我们自定义过滤器和简单的标签我们需要
- 在app中创建templatetags文件夹(文件夹名字必须的是这个)
- 创建任意 .py 文件,如:my_tags.py
#!/usr/bin/env python #-*- coding:utf-8 -*- from django import template from django.utils.safestring import mark_safe register = template.Library() #register的名字是固定的,不可改变 @register.filter def filter_multi(x,y): return x*y @register.simple_tag def simple_tag_multi(x,y): return x*y @register.simple_tag def my_input(id,arg): result = "<input type='text' id='%s' class='%s' />" %(id,arg) return mark_safe(result)
如何调用自定义filter和simple_tag
在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}
在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.
{% load my_tags %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ num|filter_multi:2 }} #24 <br>
{{ num|filter_multi:"[22,333,4444]" }}<br>
<p>{% simple_tag_multi 2 5 %} 参数不限,但不能放在if for语句中 </p>
{% simple_tag_multi num 5 %}
</body>
</html>
视图和路由的配置文件
#路由 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^index/',views.index), ] #视图 from django.shortcuts import render,HttpResponse # Create your views here. def index(request): num=12 return render(request,"index.html",locals())
注:filter可以用在if等语句后,simple_tag不可以
模板引入和继承
模板引入
{% include %}该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。
引入方法
{% load staticfiles %} HTML相关内容 {% include '要引入的html文件名' %}
模板继承
常见的 Web 开发问题: 在整个网站中,如何减少共用页面区域(比如站点导航)所引起的重复和冗余代码?
解决该问题的传统做法是使用 服务器端的 includes ,你可以在 HTML 页面中使用该指令将一个网页嵌入到另一个中。 事实上, Django 通过刚才讲述的 {% include %} 支持了这种方法。 但是用 Django 解决此类问题的首选方法是使用更加优雅的策略—— 模板继承 。
本质上来说,模板继承就是先构造一个基础框架模板,而后在其子模板中对它所包含站点公用部分和定义块进行重载
如果子板不自定义块,默认会继承母板的所有内容(包括模板的css,js),如果子板要修改css或js文件,在相应地方加块,就可以了
例如:
简单写一个子板继承母板
定义母板文件base.html,定义子板要自定义的块
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <H1> HAHA </H1> {% block content %} <h2>子板自定义修改的内容</h2> {% endblock %} </body> </html>
定义子板文件child.html
{% extends "base.html" %}
子板如果就这么一行代码,就会继承母板的所有内容,这{% extends "母板文件" %}必须写在最首行
如果要自定义修改块
{% extends "base.html" %} {% block content %} <h2 style="color: red">我是子板,修改了母板自定义块的内容</h2> {% endblock %}
注:
母板
{% block 自定义块名%}
子板的块
{% block 母板中相应设置的块名 }
{% block %} 内容 {% endblock %}的标签也是成对出现
使用继承的注意事项:
- 创建 base.html 模板,在其中定义站点的主要外观感受。 这些都是不常修改甚至从不修改的部分。
- 为网站的每个区域创建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。这些模板对base.html 进行拓展,并包含区域特定的风格与设计。
- 为每种类型的页面创建独立的模板,例如论坛页面或者图片库。 这些模板拓展相应的区域模板。
模板继承的一些诀窍:
- 如果在模板中使用 {% extends %} ,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。
- 一般来说,基础模板中的 {% block %} 标签越多越好。 记住,子模板不必定义父模板中所有的代码块,因此你可以用合理的缺省值对一些代码块进行填充,然后只对子模板所需的代码块进行(重)定义。 俗话说,钩子越多越好。
- 如果发觉自己在多个模板之间拷贝代码,你应该考虑将该代码段放置到父模板的某个 {% block %} 中。如果你需要访问父模板中的块的内容,使用 {{ block.super }}这个标签吧,这一个魔法变量将会表现出父模板中的内容。 如果只想在上级代码块基础上添加内容,而不是全部重载,该变量就显得非常有用了。
- 不允许在同一个模板中定义多个同名的 {% block %} 。 存在这样的限制是因为block 标签的工作方式是双向的。也就是说,block 标签不仅挖了一个要填的坑,也定义了在父模板中这个坑所填充的内容。如果模板中出现了两个相同名称的 {% block %} 标签,父模板将无从得知要使用哪个块的内容。
八、Model层
1、基本创建
Django提供了一个抽象层("Model")的构建和管理Web应用程序的数据。
Django使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。
- 每个模型是一个Python类,子类
django.db.models.model
- 模型中的每个属性代表一个数据库字段。
# DEMO class Student(models.Model): name = models.CharField(max_length=10) sex = models.CharField(max_length=10) age = models.IntegerField() grade = models.ForeignKey('Grade')
1 AutoField(Field) 2 - int自增列,必须填入参数 primary_key=True 3 4 BigAutoField(AutoField) 5 - bigint自增列,必须填入参数 primary_key=True 6 7 注:当model中如果没有自增列,则自动会创建一个列名为id的列 8 from django.db import models 9 10 class UserInfo(models.Model): 11 # 自动创建一个列名为id的且为自增的整数列 12 username = models.CharField(max_length=32) 13 14 class Group(models.Model): 15 # 自定义自增列 16 nid = models.AutoField(primary_key=True) 17 name = models.CharField(max_length=32) 18 19 SmallIntegerField(IntegerField): 20 - 小整数 -32768 ~ 32767 21 22 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23 - 正小整数 0 ~ 32767 24 IntegerField(Field) 25 - 整数列(有符号的) -2147483648 ~ 2147483647 26 27 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28 - 正整数 0 ~ 2147483647 29 30 BigIntegerField(IntegerField): 31 - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 32 33 自定义无符号整数字段 34 35 class UnsignedIntegerField(models.IntegerField): 36 def db_type(self, connection): 37 return 'integer UNSIGNED' 38 39 PS: 返回值为字段在数据库中的属性,Django字段默认的值为: 40 'AutoField': 'integer AUTO_INCREMENT', 41 'BigAutoField': 'bigint AUTO_INCREMENT', 42 'BinaryField': 'longblob', 43 'BooleanField': 'bool', 44 'CharField': 'varchar(%(max_length)s)', 45 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 46 'DateField': 'date', 47 'DateTimeField': 'datetime', 48 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 49 'DurationField': 'bigint', 50 'FileField': 'varchar(%(max_length)s)', 51 'FilePathField': 'varchar(%(max_length)s)', 52 'FloatField': 'double precision', 53 'IntegerField': 'integer', 54 'BigIntegerField': 'bigint', 55 'IPAddressField': 'char(15)', 56 'GenericIPAddressField': 'char(39)', 57 'NullBooleanField': 'bool', 58 'OneToOneField': 'integer', 59 'PositiveIntegerField': 'integer UNSIGNED', 60 'PositiveSmallIntegerField': 'smallint UNSIGNED', 61 'SlugField': 'varchar(%(max_length)s)', 62 'SmallIntegerField': 'smallint', 63 'TextField': 'longtext', 64 'TimeField': 'time', 65 'UUIDField': 'char(32)', 66 67 BooleanField(Field) 68 - 布尔值类型 69 70 NullBooleanField(Field): 71 - 可以为空的布尔值 72 73 CharField(Field) 74 - 字符类型 75 - 必须提供max_length参数, max_length表示字符长度 76 77 TextField(Field) 78 - 文本类型 79 80 EmailField(CharField): 81 - 字符串类型,Django Admin以及ModelForm中提供验证机制 82 83 IPAddressField(Field) 84 - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 85 86 GenericIPAddressField(Field) 87 - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 88 - 参数: 89 protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 90 unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" 91 92 URLField(CharField) 93 - 字符串类型,Django Admin以及ModelForm中提供验证 URL 94 95 SlugField(CharField) 96 - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) 97 98 CommaSeparatedIntegerField(CharField) 99 - 字符串类型,格式必须为逗号分割的数字 100 101 UUIDField(Field) 102 - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证 103 104 FilePathField(Field) 105 - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能 106 - 参数: 107 path, 文件夹路径 108 match=None, 正则匹配 109 recursive=False, 递归下面的文件夹 110 allow_files=True, 允许文件 111 allow_folders=False, 允许文件夹 112 113 FileField(Field) 114 - 字符串,路径保存在数据库,文件上传到指定目录 115 - 参数: 116 upload_to = "" 上传文件的保存路径 117 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 118 119 ImageField(FileField) 120 - 字符串,路径保存在数据库,文件上传到指定目录 121 - 参数: 122 upload_to = "" 上传文件的保存路径 123 storage = None 存储组件,默认django.core.files.storage.FileSystemStorage 124 width_field=None, 上传图片的高度保存的数据库字段名(字符串) 125 height_field=None 上传图片的宽度保存的数据库字段名(字符串) 126 127 DateTimeField(DateField) 128 - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] 129 130 DateField(DateTimeCheckMixin, Field) 131 - 日期格式 YYYY-MM-DD 132 133 TimeField(DateTimeCheckMixin, Field) 134 - 时间格式 HH:MM[:ss[.uuuuuu]] 135 136 DurationField(Field) 137 - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型 138 139 FloatField(Field) 140 - 浮点型 141 142 DecimalField(Field) 143 - 10进制小数 144 - 参数: 145 max_digits,小数总长度 146 decimal_places,小数位长度 147 148 BinaryField(Field) 149 - 二进制类 150 151 字段
1 null 数据库中字段是否可以为空 2 db_column 数据库中字段的列名 3 db_tablespace 4 default 数据库中字段的默认值 5 primary_key 数据库中字段是否为主键 6 db_index 数据库中字段是否可以建立索引 7 unique 数据库中字段是否可以建立唯一索引 8 unique_for_date 数据库中字段【日期】部分是否可以建立唯一索引 9 unique_for_month 数据库中字段【月】部分是否可以建立唯一索引 10 unique_for_year 数据库中字段【年】部分是否可以建立唯一索引 11 12 verbose_name Admin中显示的字段名称 13 blank Admin中是否允许用户输入为空 14 editable Admin中是否可以编辑 15 help_text Admin中该字段的提示信息 16 choices Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作 17 如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1) 18 19 error_messages 自定义错误信息(字典类型),从而定制想要显示的错误信息; 20 字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date 21 如:{'null': "不能为空.", 'invalid': '格式错误'} 22 23 validators 自定义错误验证(列表类型),从而定制想要的验证规则 24 from django.core.validators import RegexValidator 25 from django.core.validators import EmailValidator,URLValidator,DecimalValidator, 26 MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator 27 如: 28 test = models.CharField( 29 max_length=32, 30 error_messages={ 31 'c1': '优先错信息1', 32 'c2': '优先错信息2', 33 'c3': '优先错信息3', 34 }, 35 validators=[ 36 RegexValidator(regex='root_d+', message='错误了', code='c1'), 37 RegexValidator(regex='root_112233d+', message='又错误了', code='c2'), 38 EmailValidator(message='又错误了', code='c3'), ] 39 ) 40 41 参数 42 43 Field参数
2、连表结构例如在建表的时候应该了解到如何
- 一对多:models.ForeignKey(其他表)
- 多对多:models.ManyToManyField(其他表)
- 一对一:models.OneToOneField(其他表)
-
应用场景:
- 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。 - 多对多:在某表中创建一行数据是,有一个可以多选的下拉框
例如:创建用户信息,需要为用户指定多个爱好 - 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了
例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据
- 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)
3、表操作
a、基本操作
# 增 # # models.Tb1.objects.create(c1='xx', c2='oo') 增加一条数据,可以接受字典类型数据 **kwargs # obj = models.Tb1(c1='xx', c2='oo') # obj.save() # 查 # # models.Tb1.objects.get(id=123) # 获取单条数据,不存在则报错(不建议) # models.Tb1.objects.all() # 获取全部 # models.Tb1.objects.filter(name='seven')# 获取指定条件的数据 # 删 # # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据 # 改 # models.Tb1.objects.filter(name='seven').update(gender='0') # 将指定条件的数据更新,均支持 **kwargs # obj = models.Tb1.objects.get(id=1) # obj.c1 = '111' # obj.save()
b、进阶操作(了不起的双下划线)
# 获取个数 # # models.Tb1.objects.filter(name='seven').count() # 大于,小于 # # models.Tb1.objects.filter(id__gt=1) # 获取id大于1的值 # models.Tb1.objects.filter(id__gte=1) # 获取id大于等于1的值 # models.Tb1.objects.filter(id__lt=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lte=10) # 获取id小于10的值 # models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值 # in # # models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据 # models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in # isnull # Entry.objects.filter(pub_date__isnull=True) # contains # # models.Tb1.objects.filter(name__contains="ven") # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 # models.Tb1.objects.exclude(name__icontains="ven") # range # # models.Tb1.objects.filter(id__range=[1, 2]) # 范围bettwen and # 其他类似 # # startswith,istartswith, endswith, iendswith, # order by # # models.Tb1.objects.filter(name='seven').order_by('id') # asc # models.Tb1.objects.filter(name='seven').order_by('-id') # desc # group by # # from django.db.models import Count, Min, Max, Sum # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num')) # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id" # limit 、offset # # models.Tb1.objects.all()[10:20] # regex正则匹配,iregex 不区分大小写 # # Entry.objects.get(title__regex=r'^(An?|The) +') # Entry.objects.get(title__iregex=r'^(an?|the) +') # date # # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1)) # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1)) # year # # Entry.objects.filter(pub_date__year=2005) # Entry.objects.filter(pub_date__year__gte=2005) # month # # Entry.objects.filter(pub_date__month=12) # Entry.objects.filter(pub_date__month__gte=6) # day # # Entry.objects.filter(pub_date__day=3) # Entry.objects.filter(pub_date__day__gte=3) # week_day # # Entry.objects.filter(pub_date__week_day=2) # Entry.objects.filter(pub_date__week_day__gte=2) # hour # # Event.objects.filter(timestamp__hour=23) # Event.objects.filter(time__hour=5) # Event.objects.filter(timestamp__hour__gte=12) # minute # # Event.objects.filter(timestamp__minute=29) # Event.objects.filter(time__minute=46) # Event.objects.filter(timestamp__minute__gte=29) # second # # Event.objects.filter(timestamp__second=31) # Event.objects.filter(time__second=2) # Event.objects.filter(timestamp__second__gte=31)
c、连表操作(了不起的双下划线)
1 # DEMO 2 # 班级和老师存在多对多关系、班级和学生存在一对多关系 3 from django.db import models 4 5 class Classes(models.Model): 6 titile = models.CharField(max_length=32) 7 m = models.ManyToManyField('Teachers') 8 9 10 class Teachers(models.Model): 11 name = models.CharField (max_length=32) 12 13 14 class Student(models.Model): 15 username = models.CharField(max_length=32) 16 age = models.IntegerField() 17 gender = models.BooleanField() 18 cs = models.ForeignKey(Classes)
1 # 增 2 # Teachers.objects.create(name='root') 3 # obj = Teachers(name='root') 4 # obj.save() 5 # 查 6 # Teachers.objects.all() 7 # Teachers.objects.filter(id=1) 8 # Teachers.objects.filter(id=1,name='root') 9 # result = Teachers.objects.filter(id__gt=1) 10 # [obj(id,name),] 11 # result = Teachers.objects.filter(id__gt=1).first() 12 # 删 13 # Teachers.objects.filter(id=1).delete() 14 # 改 15 # Teachers.objects.all().update(name='alex') 16 # Teachers.objects.filter(id=1).update(name='alex')
1 # 增加 2 # Student.objects.create(username='东北',age=18,gender='男',cs_id=1) 3 # Student.objects.create(username='东北',age=18,gender='男',cs= Classes.objects.filter(id=1).first() ) 4 # 查看 5 """ 6 ret = Student.objects.all() 7 # [] 8 # [ obj(..),] 9 # [ obj(1 东北 18 男 1),obj(2 东北1 118 男 2),obj(..),] 10 for item in ret: 11 print(item.id) 12 print(item.username) 13 print(item.age) 14 print(item.gender) 15 print(item.cs_id) 16 print(item.cs.id) 17 print(item.cs.name) 18 """ 19 # 删除 20 # Student.objects.filter(id=1).delete() 21 # Student.objects.filter(cs_id=1).delete() 22 23 # cid = input('请输入班级ID') 24 # Student.objects.filter(cs_id=cid).delete() 25 26 # cname = input('请输入班级名称') 27 # Student.objects.filter(cs_id=cid).delete() 28 # Student.objects.filter(cs__name=cname).delete()
1 """ 2 班级: 3 id title 4 1 3班 5 2 4班 6 3 5班 7 老师: 8 id title 9 1 Alex 10 2 老妖 11 3 瞎驴 12 4 Eric 13 老师班级关系表(类): 14 id 班级id 老师id 15 1 1 2 16 2 1 3 17 4 2 2 18 5 2 3 19 6 2 4 20 7 1 5 21 22 23 # 增 24 obj = Classes.objects.filter(id=1).first() #1 3班 25 obj.m.add(2) 26 obj.m.add([4,3]) 27 28 # obj = Classes.objects.filter(id=2).first() #1 3班 29 # obj.m.add(2) 30 # obj.m.add([4,3]) 31 32 obj = Classes.objects.filter(id=1).first() #1 3班 33 # 删除 34 # obj.m.remove([4,3]) 35 # 清空 36 obj.m.clear() 37 # 重置 38 obj.m.set([2,3,5]) 39 40 # 查第三张表 41 # 把3班的所有老师列举 42 obj = Classes.objects.filter(id=1).frist() 43 obj.id 44 obj.titile 45 ret = obj.m.all() # 第三张表 46 # ret是一个 [ 老师1(id,name),obj(id,name) ]
d、其它操作
1 # extra 2 # 3 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) 4 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) 5 # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) 6 # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) 7 # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 8 9 # F 使用查询条件的值,专门取对象中某列值的操作 10 # 11 # from django.db.models import F 12 # models.Tb1.objects.update(num=F('num')+1) 13 14 15 # Q 与 或 非 的关系构建搜索条件 16 # 17 # 方式一: 18 # Q(nid__gt=10) 19 # Q(nid=8) | Q(nid__gt=10) 20 # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 21 # 方式二: 22 # con = Q() 23 # q1 = Q() 24 # q1.connector = 'OR' 25 # q1.children.append(('id', 1)) 26 # q1.children.append(('id', 10)) 27 # q1.children.append(('id', 9)) 28 # q2 = Q() 29 # q2.connector = 'OR' 30 # q2.children.append(('c1', 1)) 31 # q2.children.append(('c1', 10)) 32 # q2.children.append(('c1', 9)) 33 # con.add(q1, 'AND') 34 # con.add(q2, 'AND') 35 # 36 # models.Tb1.objects.filter(con) 37 38 39 # exists()方法来检查是否有数据 exists()的检查可以避免数据放入queryset的cache。 40 # obj = Book.objects.filter(id=4) 41 # if obj.exists():print("hello world!") 42 43 # 执行原生SQL 44 # 45 # from django.db import connection, connections 46 # cursor = connection.cursor() # cursor = connections['default'].cursor() 47 # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) 48 # row = cursor.fetchone() 49 50 Q、F、exists()
e、补充
# values 取到的是字典集合 # values_list 取到的是没有键的元祖形式 # get 只有在能取到一条数据的时候才不会报错(不推荐) # filter([筛选条件]) # all() 俩者取到的都是Query set集合对象 是可迭代、可切片、索引取值 # iterator() ORM的惰性机制 # Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet # 并不会马上执行sql,而是当调用QuerySet的时候才执行。