第六模块:WEB框架开发之Django框架开发学习笔记1蓝蓝的白云天!

WEB应用就是服务器上的程序,它接受客户端(浏览器)的请求,并响应请求发送字符串给客户端.

2.1socket套节字网络数据传输必须要用到socket,(其实本地电脑的应用程序和操作系统之间也需要socket)

2.2实例:一个简单的WEB应用程序

#一个简单的WEB应用程序importsocketsock=socket.socket()sock.bind(("127.0.0.1",8800))sock.listen(5)while1:print('serverwaiting......')conn,addr=sock.accept()data=conn.recv(1024)print('data',data)#conn.send(b"helloluffycity")#用浏览器访问时,显示该网页无法正常运作127.0.0.1发送的响应无效。ERR_INVALID_HTTP_RESPONSE.因为浏览器无法识别发过来的数据.conn.send(b"HTTP/1.1200OK\r\n\r\nhelloluffycity")#规范的WEB请求格式,浏览器的页面可以正常显示了.conn.close()一个简单的WEB应用程序三.WEB应用程序23.1发送字符串,让浏览器渲染出带html标签

的字符串

3.2WEB应用程序读取html文件,并发送到客户端,客户端浏览器进行渲染

4.1包含以下三个部分:

(每一个小块数据用\r\n区隔开)

a.请求首行包含:请求方式(get或post)请求路径(url)协议(HTTP/1.1)

b.请求头(若干个键值对)常包含:HostConnectioncontent-Type等

c.请求体连续两个\r\n后的就是请求体只有post请求才有请求体,get请求没有请求体

4..2请求数据实例

GET/HTTP/1.1\r\nHost:127.0.0.1:8899\r\nConnection:keep-alive\r\nUpgrade-Insecure-Requests:1\r\nUser-Agent:Mozilla/5.0(WindowsNT6.1;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/86.0.4240.75Safari/537.36\r\nAccept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\nSec-Fetch-Site:none\r\nSec-Fetch-Mode:navigate\r\nSec-Fetch-User:1\r\nSec-Fetch-Dest:document\r\nAccept-Encoding:gzip,deflate,br\r\nAccept-Language:zh-CN,zh;q=0.9\r\n\r\n'ViewCode

4.3get与post的使用区别

get一般应用于查询,post应用于更新数据库数据

只有POST请求才有请求体

服务器的接收到的请求(末尾黄色字是请求体,即浏览器用户输入的用户名和密码):

一个典型的服务器端post请求源代码

-get提交的数据会放在URL之后,以分割URL和传输数据,参数之间以&相连,如EditBookname=test1&id=123456.POST方法是把提交的数据放在HTTP包的请求体中.

-get提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.

-get与post请求在服务端获取请求数据方式不同.

6.2响应格式(浏览器接收到服务器发来的信息)

6.3自定义响应头(黄色字符部分)

conn.send(b"HTTP/1.1200OK\r\nContent-Type:text\r\n\r\n%s"%data)

6.4响应状态码

状态码如200OK,以3位数字和原因成。数字中的一位指定了响应别,后两位无分。响应别有以5种。

重定向的解释:浏览器向服务器发送请求,服务器接收到后再发送响应信息给浏览器,该响应信息告诉浏览器需要(浏览器再发一次请求)转到另外一个资源.

-wsgi是接口协议

7.1wsgiref模块功能

-按照HTTP请求协议格式进行解包(解析数据)

-按照HTTP响应协议封装数据

-wgiref模块封装了socket

-让WEB应用开发者专注于WEB业务开发

-wsgiref做的简单的,根据用户不的输入,实现不同网页的效果

-路由的解释

9.1浏览器默认会发送图标请求

-此响应时,浏览器只接收图片,如果发送字符串,则字符串不会显示.

-其实也是解了耦合

增添功能,只需要修改路由文件,视图文件,模板等就可以了.

如果没有数据库,就没有什么意义.

大而全,组建特别多

14.1mvc和mtv模型(模型的主要目的是解耦合)

15.1cmd纯命令行,安装Django模块命令

pipinstallDjango#注意:Django首字母大写

如果提示pip错误,则先python.exe-mpipinstall--upgradepip,注意该命令前面不能带路径

15.2cmd纯命令行,在当前文件夹下创建一个mysite项目

django-admin.pystartprojectmysite#注意首字母d是小写

项目的文件夹树,manage.py为启动文件,相当于之前的main.py

manage.py----Django项目里面的工具,通过它可以调用djangoshell和数据库

settings.py----包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量

urls.py----负责把URL模式映射到应用程序

15.3cmd纯命令行,在mysite目录下创建应用blog(注意:mysite是项目文件夹,blog是应用程序文件夹,一个项目中可以包含多个应用程序)

首先cdmysite文件夹,进入sysite项目根目录

然后pythonmanage.pystartappblog创建blog应用程序

下图为创建blog应用后的文件夹

下图为blog应用程序的文件结构

15.4cmd命令下,启动Django项目

pythonmanage.pyrunserver8000

16.1.1创建一个Django项目

16.1.2生成的一个fisrt_pro项目,新建一个app01程序的目录

16.1.3几个文件的代码

16.2Django服务(请求)执行过程(MPV过程)

---->1.urls.py(由它决定用户发送的路径交给哪个视图函数处理)---->2.views.py(主要逻辑处理)---->3.models.py(涉及到数据库的从这里取)---->4.timer.html(最终的返回页面的模板)---->

17.1什么叫静态文件

项目中的css,js都应当处理为静态文件.项目中的任何文件都需要Django去找,最终都是由客户端的浏览器去执行的,引入jquery-3.1.1.js时就需要注意文件路径问题(不能当成客户端的本地文件去执行),js文件需要写成服务器的地址.

17.2如何配置静态文件

在项目的根目录下创建static文件夹,所有静态文件都放入其中.此时通过客户端浏览器无法直接访问该文件,因为(Django采用虚拟文件夹的方式访问)客户端的所有访问路径都经过urls.py路由处理,而urls.py中没有添加关于js的路由.在settings.py中配置一下就可以通过别名访问了.配置方法在下面.

处理settings.py文件

STATIC_URL='/static/'#路径别名(虚拟目录),客户端浏览器输入地址(路径)可直接访问了STATICFILES_DIRS=[os.path.join(BASE_DIR,'statics'),#实际路径,这里是方便为了区分才使用statics这个名字,正式使用时,实际目录和别名都用static]模板文件引入jquery-3.5.1.js,文字点击变为红色效果timer.html

18.1html文件中引入css和js

css文件和js文件也是静态文件,需要放到项目中的static文件夹下,针对不同的应用可以在static文件夹下再建立应用的子文件夹,比如app01,将app01应用程序的css和js文件放到app01文件夹下.这里需要注意的是,在html中引入css\js文件时需要使用static静态目录.

文件目录如下:

19.1re_path模块,Django1版本的路由

路由配置:路径-------->视图函数

采用正则表达式re匹配路径,(路径中加括号的分组)

fromdjango.shortcutsimportrender,HttpResponse#HttpResponse#Createyourviewshere.deftimer(request):importtimectime=time.time()returnrender(request,'timer.html',{'ctime':ctime})defspecial_case_2003(request):returnHttpResponse("special_case_2003")defyear_archive(request,year):returnHttpResponse(year)defmonth_archive(request,year,month):returnHttpResponse(year+"-"+month)defarticle_detail(request,year,month,date):returnHttpResponse(year+"-"+month+"-"+date)视图View.py

19.2注意:

-若要从URL中获取一值,只需要在它周围放置一对圆括号.

-不需要添加一个前导的反斜杠,应为每个URL都有.例如,应该是^articles而不是^/articles.

-每个正则表达式前面的"r"是可选的,但建议加上.它告诉python这个字符串是"原始的"----字符串中任何字符都不应该转义.

20.1为路径中的分组起名字,关键字参数传参

全局urls.py和一个app应用程序的urls.py,文件结构

21.2两个URLS.py代码

全局urls.py中的关键代码

第二次是在login页面点击提交按钮,这是POST请求

#'django.middleware.csrf.CsrfViewMiddleware',

23.1用别名指代URL.在模板中进行反向解析

urls.py中,对于路径采用别名.应用场景:当产品经理要求更改访问路径的时候,只需要改urls.py中的路径名就可以了,其它文件无需改动.

使用urls.py中使用别名,增加参数name='别名',注意在模板文件中把action中的路径改为规定的格式{%url"别名"%}.views.py中的函数名称与别名要保持一致.

24.1在视图函数中进行反向解析

可以在后台获取到用户访问的完整路径

需要在视图函数中导入反向解析函数reverse,需要注意的是,如果urls.py路径中包含正则表达式,则需要在视图函数中增加args参数

/app/articles/2005/

25.1名称空间(namespace),也叫命名空间,是表示标示符的可见范围.

由于name没有作用域,Django在反解析URL时,会在项目全局顺序搜索,当查找到第一个name指定URL时,立即返回,我们在开发项目时,会经常使用name属性反解除URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入命名空间.

25.2实例

25.2.1使用pycharm的命令行窗口创建新应用app02

25.2.2创建新应用后的目录如下:

25.2.3为全局urls.py添加app02的路由分发

fromdjango.contribimportadminfromdjango.urlsimportpath,re_path,includefromappimportviews,urlsurlpatterns=[re_path(r'^app/',include("app.urls")),#分发到app中re_path(r'^app02/',include("app02.urls")),#分发到app02中]全局urls.py文件25.2.4为app02增加index视图

fromdjango.shortcutsimportrender,HttpResponse#Createyourviewshere.defindex(request):returnHttpResponse("index2")app02的views.py25.2.5为app02的urls.py增加index的路由解析

25.2.7为app应用添加index视图和路由,以及访问的效果.

25.2.8分别为app和app01下的两个index加别名

应用程序中的urls.py文件中路由解析

re_path('index/',views.index,name='index')

现在就有两个index,名字就重复了.

25.2.9两个index,反向解析,就出问题了.

先分别为两个app的views.py添加名称index的反向解析reverse('index')

分别访问两个index,反向解析路径,得到的路径是相同的,就出问题了.(覆盖了)

25.2.10下面解决名称相同,的反向解析相同的问题

25.2.11在全局urls.py中给include()路由分发添加名称空间namespace

urlpatterns=[path('admin/',admin.site.urls),path('timer/',views.timer),re_path('login.html',views.login,name='login'),re_path(r'^app/',include(("app.urls","app"))),#名称空间namespace="app"注意这里增加了一个元组re_path(r'^app02/',include(("app02.urls","app02"))),#名称空间namespace="app02"]全局urls.py25.2.12再给两个app的views.py文件中的反向解析添加上namespace的名称

27.1django2.0的path.re_path是django1.0版本的语法

re_path传的值是字符串,如果要使用数字,还需要进行转换.path方法就是解决这类问题而生的.

urlpatterns=[path('admin/',admin.site.urls),path('timer/',views.timer),path('login/',views.login),path("articles/",views.path_year),#path_year(request,2001)]全局urls.py

27.2path的5个转化器

str,匹配除了路径分隔符/之外的非空字符串,这是默认的形式

int,匹配正整数,包含0

slug,匹配字母,数字以及横杆,下划线组成的字符串

uuid,匹配格式化的uuid,如075194d3-6885-417e-a8a8-6c931e272f00

path,匹配任何非空字符串,包含了路径分隔符

28.1对于一些复杂或者复用的需要,可以定义自己的转化器.转化器是一个类或接口,它的要求有三点:

28.2自定义path转化器应用实例.(使用register_converter将其注册到URL配置中)

29.2有名分组按关键字传参

29.3分发include

29.4反向解析利用别名

29.5名称空间

29.6path

30.1在视图函数中获取用户的请求数据

先关闭settings.py中的一项设置项目才可正常运行

获取到的get请求数据,是个字典格式.

获取值:

request.GET.get("name")request.POST.get("name")

re_path("^$",views.index)或者path(r"",views.index),

30.3方法request.get_full_path(),获取完成的路径可保护get数据

下面来看看两个区别:

print(request.path)#只能获取路径

print(request.get_full_path())#路径+get请求的数据

后台显示结果:

31.1最终都是返回HttpResponse(),render()也会转化为HttpResponse()

31.1.1HttpResponse("

ok

")

31.1.2render(request,"index.html",{"变量名":变量值})#把变量传递给模板,注意书写字典格式

模板文件index.html中使用{{变量名}}#模板语法,注意书写格式,双大括号

32.1字典,列表,对象,字符串,等更丰富的数据类型怎么嵌入到模板中

模板语法:渲染变量用{{}}用句点符深度查询,过滤器

渲染标签用{%%}

使用句点符达到的效果就是从字典,列表等数据中再获取指定位置的值

把视图中的变量按照某种形式在模板中渲染出来

33.1语法:

{{obj|filter_name:param}}33.2日期过滤器date

视图文件代码:

importdatetime

date=datetime.datetime.now()

模板文件代码:

{{date}}

显示效果:Jan.17,2021,1:06p.m.(显示的不友好)

{{date|date:'Y-m-d'}}

显示效果:2021-01-17这里date|date,两个date后面一个date是过滤器名称

下图为显示效果对比:

33.3default过滤器,默认在数据为空的情况下的显示内容

视图文件代码:name_list=[]列表值为空

模板文件代码:

{{name_list}}

显示效果:[]

{{name_list|default:"姓名数据为空"}}

显示效果:姓名数据为空

33.4length过滤器,返回值的长度

{{value|length}}如果value是['a','b','c'],那么输出是3

33.5filesizeformat,将值格式化为一个"人类可读"文件尺寸.主要用于显示文件的大小

{{value|filesizeformat}}如果value是123456789,输出将会是117.7MB

33.6slice过滤器,将字符串切片

{{value|slice:"2:-1"}}如果value="helloword",将输出llowor

33.7truncatechars,截断过滤器,如果字符串字符多余指定的字符数量,那么会被截断.截断的字符串将以可翻译的省略号序列"..."结尾

{{value|truncatechars:9}}参数9,就是要显示(截断)的字符数包含...一共是9个字符,(注意一个字母就是一个字符)

{{hello_str|truncatewords:1}}truncatewords参数3,表示显示的单词数量,不包含...(注意hello表示一个单词)

下图为显示效果:

33.8safe过滤器,强调不转义,用在变量是html标签时

33.9add加法过滤器

{{l.0|add:100}}如果l.0=100,那么输出200

33.10upper转大写过滤器

{{name|upper}}如果name="hao",那么输出HAO

34.1标签看起来像这样的:{%tag%}.标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模板中.一些标签需要开始和结束标签(例如{%tag%}...标签内容...{%endtag%})

34.2最少需要掌握for标签和if标签

34.3for循环标签

遍历每一个元素:

{%forpersoninperson_list%}

{{person.name}}

{%endfor%}可以利用{%forobjinlistreversed%}反向完成循环。

遍历一个字典:

{%forkey,valindic.items%}

{{key}}:{{val}}

{%endfor%}如果{%forkeyindic%}则只遍历key

注:循环序号可以通过{{forloop}}显示

34.4for...empty数据为空时的处置.为空的时候不会渲染.当使用for...empty时就可以渲染指定的内容.

for标签带有一个可选的{%empty%}从句,以便在给出的组是空的或者没有被找到时,可以有所操作。

{%forpersoninperson_list%}

{{person.name}}

{%empty%}

sorry,nopersonhere

{%endfor%}34.5if标签

{%if%}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。

34.6with标签,把长名字缩减成短名字

{%withperson_list.1.nameasn%}

{{n}}使用n就相当于用person_list.1.name,当深度查询非常长的时候用

{%endwith%}

使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

例如:

{%withtotal=business.employees.count%}{{total}}employee{{total|pluralize}}{%endwith%}34.7csrf_token这个标签用于跨站请求伪造保护

此功能与全局settings.py中的'django.middleware.csrf.CsrfViewMiddleware'有关系

在表单的post提交中会出现下面的提示Forbidden(403):

如果在模板中添加csrf_token就不会出现Forbidden(403)错误了.

{%csrf_token%}查看网页源代码,多出了一个input标签,多出了的input就是{%csrf_token%}的功劳.有了它就可以正确提交post请求.(识别是不是第二次访问,拦截判断用)

34.1自定义标签与过滤器,流程固定,背下来

1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

2、在app中创建templatetags模块(模块名只能是templatetags)

3、创建任意.py文件,如:my_tags.py

4、在使用自定义simple_tag和filter的html文件中导入之前创建的my_tags.py

5、使用simple_tag和filter(如何调用)

注意:filter可以用在if等语句后,simple_tag不可以

34.2实例自定义乘法过滤器

34.2.1在settings.py中配置app

34.2.2在app中创建templatetags模块(模块名只能是templatetags)

34.2.3创建my_tag_filter.py文件,目录如下:

fromdjangoimporttemplateregister=template.Library()@register.filterdefmulti_filter(x,y):#自定义乘法过滤器returnx*y34.2.4在使用自定义multi_filter的html文件中导入之前创建的my_tag_filter.py

{%loadmy_tag_filter%}34.2.5使用自定义multi_filter(如何调用)

36.1{%include'advertise.html'%}在html模板文件中嵌入其它html模板文件

两个父子模板文件在目录中的位置

在index.html文件中的左侧嵌入advertise.html

advertise.html文件全部代码

最终效果,左侧三个面板为{%include'advertise.html'%}嵌入的内容:

建立一个新页面order.html该页面想和前面的index.html拥有相同的头部和左侧面板,这就用到了继承.

新建base.html基础模板页面,作为父页面,复制index.html中的内容到该业中,该页面中,包含css,头部和左侧面板,内容部分被删除,代替以block盒子{%blockcon%}在这个中间加入该页面独特内容{%endblock%},代码如下:

{#继承自base.html,包含头部,左侧等内容#}{%extends'base.html'%}{%blockcon%}{#index.html页面独特的内容#}

首页内容区域

首页内容区域

首页内容区域

首页内容区域

首页内容区域

首页内容区域

首页内容区域

首页内容区域

{%endblock%}index.html新建订单页面orders.html,继承base.html页面,

{%extends'base.html'%}{%blockcon%}

订单页面

订单页面

订单页面

订单页面

订单页面

订单页面

订单页面

{%endblock%}orders.html可以在base.html页面中留多个盒子,甚至标签都可以设计为一个盒子.下面的代码是增加了一个控制标题的盒子{%blocktitle%}.模板页面中可以添加多个盒子,以解决代码复用的问题.

36.4注意事项

37.1Django的几大部分

url控制器,视图部分,模板部分,模型层

37.2模型层用于和数据库打交道.ORM就是用来控制数据库的.

ORM直接把python中的类转换为(翻译)mysql语句,以后我们直接编写Python类就可以控制数据库了.

注意ORM只能对表做操作,不能对库做操作.

38.1使用pycharm创建app01和orm数据库的Book表

38.1.1使用pycharm新建orm项目app01应用程序,使用cmd命令行创建orm数据库

cmd下连接mysql,进入mysql命令提示符,输入创建orm库的命令,完成数据库创建.

createdatabaseorm;

38.1.2在orm文件夹下的settings.py中修改DATABASES数据库设置如下:

importpymysqlpymysql.version_info=(1,4,13,"final",0)#防止Django版本引起错误pymysql.install_as_MySQLdb()orm下__init__.py文件中添加pymysql模块38.1.4在app01应用程序目录下的models.py文件中建立表的结构

pythonmanage.pymakemigrations#依照models.py中的类创建出表,创建迁移表

pythonmanage.pymigrate#迁移

38.1.6创建出的表,查看效果如下:

38.1.7如果想在orm转换过程中把对应的sql语句输出在后台,需要在settings中进行如下配置:

LOGGING={'version':1,'disable_existing_loggers':False,'handlers':{'console':{'level':'DEBUG','class':'logging.StreamHandler',},},'loggers':{'django.db.backends':{'handlers':['console'],'propagate':True,'level':'DEBUG',},}}ViewCode

39.1ORM主要用于增删改查数据记录

两种方法,一种是实例化类,一种的类的.objects.create方法

fromdjango.shortcutsimportrender,HttpResponsefromapp01.modelsimportBook#引入创建的表的类#Createyourviewshere.defindex(request):#添加表记录方法一#book_obj=Book(id=1,title='python红宝书',price=100,pub_date='2012-12-12',publish='人民出版社')#实例化Book对象#book_obj.save()#实例化对象的方法时,只有save一下数据才会保存到数据库中#添加表记录方法二book_obj=Book.objects.create(title='linux从入门到精通',price=80,pub_date='2013-01-25',publish='人民邮电出版社')#此种方法无需再用saveprint(book_obj.title)#.objects方法创建的,带有返回值,可以将值打印出来.print(book_obj.price)print(book_obj.pub_date)print(book_obj.publish)returnHttpResponse("ok")app01下的views.py

40.1单表查询接口,需要了解清楚的

QuerySet数据类型,Django特有的数据类型,该类型有点像列表,可以想列表一样来处理QuerySet,支持索引,支持for循环

弄清楚查询表的接口的,1每个方法的返回值2以及每个方法是谁来调用的

在app01下的models.py中的Book类中添加def__str__(self)方法用于print打印指定的数据

#app01下的models.pyfromdjango.dbimportmodels#Createyourmodelshere.classBook(models.Model):id=models.AutoField(primary_key=True)title=models.CharField(max_length=32)pub_date=models.DateField()price=models.DecimalField(max_digits=8,decimal_places=2)publish=models.CharField(max_length=32)def__str__(self):#此处功能是,在执行print命令时显示对象的titlereturnself.titleapp01下的models.py

40.2all方法:返回值是一个queryset对象,该方法由Book.objects管理器直接调用

all方法返回全部数据,all方法源代码:

fromdjango.shortcutsimportrender,HttpResponsefromapp01.modelsimportBook#Createyourviewshere.defindex(request):#查询表记录,all方法book_qs=Book.objects.all()print(book_qs)print('-')#遍历forobjinbook_qs:print(obj.title,obj.price)#输出书名,和价格print('-')#索引访问print(book_qs[1].title)#输出第二本书书名returnHttpResponse('OK')app01下的views.py后台输出效果:

40.3firsh,last方法,调用者是queryset对象,返回值是一个model对象

#查询记录,first,last方法,调用者是queryset对象,返回值是一个model对象book_obj=Book.objects.all().first()book_obj=Book.objects.all()[0]#和上面的等价book_obj=Book.objects.last()ViewCode40.4filter()筛选(过滤),根据条件筛选,返回值:queryset对象.该方法与all()方法类似.filter()方法也可以调用first()方法

#查询记录,filter()筛选,返回:queryset对象#filter()与all()的差别就是多个筛选条件,别的都一样.book_list=Book.objects.filter(price=80)#筛选出价格是80的所有记录print(book_list)#[obj1,obj2,...]book_obj=Book.objects.filter(price=80).first()ViewCode40.5get()有且只有一个查询结果时才有意义,有多个结果或没有查到时会报错.返回值:models对象

#查询记录,get()有且只有一个查询结果时才有意义,返回值:model对象book_obj=Book.objects.get(price=100)#book_obj=Book.objects.get(price=80)#因为有两本书价格是80,所以浏览器上会显示报错信息print(book_obj.title)ViewCode40.6本节app01下的views.py完整代码,包含上面4个常用的查询方法

41.1exclude()排除,方法,相当于!=不等于,所有符合条件的,然后取反.与filter()方法相反.注意:可以设置多个条件(多个条件是与的关系)

返回值是一个queryset对象,该方法由Book.objects管理器直接调用

#exclude()排除,返回值是:queryset对象.调用者:Book.objects管理器book_list=Book.objects.exclude(title='php',price=80)#可以设置多个排除条件,多个条件是与关系,也就是同时满足.filter()方法也是可以设多个条件的.print(book_list)ViewCode41.2order_by()排序,调用者:queryset对象,返回值:queryset对象

#order_by()排序ret=Book.objects.all().order_by('id')#按ID升序排列ret=Book.objects.all().order_by('-id')#条件前面加负号,按ID降序排列ret=Book.objects.all().order_by('price','id')#先按照price排序,如何price一样,则按照id排序print(ret)ViewCode41.3count()计数,调用者:queryset对象,返回值:int类型

#count()ret=Book.objects.all().count()print(ret)ViewCode41.4exist()判断表是否为空,调用者:queryset对象,返回值:布尔值True,False

#exist()判断是否为空#ret=Book.objects.all()#这种判断是否为空的方法太消耗资源(执行查询全部数据)ret=Book.objects.all().exists()#exists()方法只查询表中的一条记录,所以节约资源ifret:print('ok')ViewCode41.5queryset对象支持链式,多个方法串起来

42.1values()方法,获取对象中每个元素的值,输出列表套字典,返回值:queryset类型,调用者:queryset类型

ret=Book.objects.all().values("price")#values方法获取每个元素的值,默认可以省略all(),写成Book.objects.values("price")print(ret)print(ret[0].get('price'))#输出:"""valuers()方法的工作原理temp=[]forobjinBook.objects.all():temp.append({'price':obj.price}):returntemp"""ViewCode42.2values_list()方法,类似values()方法,输出的是列表套元组,返回值:queryset类型,调用者:queryset类型

#values_list()方法ret=Book.objects.all().values_list('price')#这里只演示了一个price字段,可以有多个字段,values()方法也可以有多个字段print(ret)#输出:ViewCode42.3distinct()去重,配合values(),values_list()方法使用.返回值:queryset类型,调用者:queryset类型

#distinct()去重,返回值:queryset类型,调用者:queryset类型ret=Book.objects.all().values('price').distinct()#获得图书的价格,去除相同价格的.print(ret)#输出:ViewCode42.4reverse():对查询结果反向排序.返回值:queryset类型,调用者:queryset类型

注意该方法需要配合order_by()方法使用,该方法是个鸡肋.这个方法只有在已经定义顺序的queryset上调用,才能对结果反向排序

#reverse()反向排序,鸡肋方法,没什么鸟用.ret=Book.objects.all().filter(price=80).order_by('id')ret2=Book.objects.all().filter(price=80).order_by('id').reverse()print(ret)print(ret2)ViewCode

42.4queryset对象支持链式,多个方法串起来

Book.objects.all().filter().order_by().filter().reverse().first()

大于小于的时候就需要用模糊查询,用双下划线.注意得到的仍然是queryset类型

43.1参数price__gt=80表示价格大于80

参数price__lt=200表示价格小于200

ret=Book.objects.filter(price__gt=80,price__lt=200)#查询价格大于80,且小于200的图书print(ret)ViewCode43.2参数title__startswith='py'表示标题以py开头的

参数title__contains='h'表示标题中包含字母h的

参数title__icontains='h'表示标题中包含字母h的,不区分大写

ret=Book.objects.filter(title__startswith='py')#查询书名以py开头的所有书ret=Book.objects.filter(title__contains='h')#查询书名中包含h的所有书ret=Book.objects.filter(title__icontains='h')#查询书名中包含h的所有书,不区分大小写print(ret)ViewCode43.4参数price__in=[80,100,200]表示只要是价格等于80或100或200

参数price__range=[80,100]查询价格在80到100之间的,包含80和100

ret=Book.objects.filter(price__in=[80,100,200])#查询只要是价格等于80或100或200的ret=Book.objects.filter(price__range=[80,100])#查询价格在80到100之间的,包含80和100print(ret)ViewCode43.5参数pub_date__year=2018查询日期是2018年的,月份和日随意,只有日期类型有此参数

参数pub_date__month=5查询月份是5月的.

ret=Book.objects.filter(pub_date__year=2021,pub_date__month=1)#查询年份是2018且月份是1月的print(ret)ViewCode43.6不止以上的这些个参数哦

44.1delete()方法,删除记录.返回值是删除的数据条数

delete()方法的调用对象是queryset对象,model对象也可以调用它.

#删除记录#ret=Book.objects.filter(price=100).delete()#queryset对象调用delete()#print(ret)#返回值:(1,{'app01.Book':1})Book.objects.filter(price=80).first().delete()#model对象调用delete()ViewCode44.2update()方法,修改记录.update()的调用者只能是queryset对象.

#修改记录Book.objects.filter(title='PHP').update(title='php零基础入门')#注意,筛选出多少条记录,就会修改多少条.返回值是条数ViewCode

系统功能简介:可以新建图书,查看图书数据,删除图书,修改图书信息.

1.建立数据库的表结构,即在models.py文件中设计Book表的结构,只要创建一个pythonBook类就可以了.

2.迁移数据库,即通过pycharm底部Terminal的,输入两条迁移命令.这里数据库使用了Django的默认sqlite3数据库.迁移完成后能看到在根目录中创建了db.sqlite3的数据库文件,pycharm窗口的的右侧可以打开查看db.效果如下,book表结构清晰可见:

3.由于本系统需要用到bootstrap等,所以需要对文件目录进行修改

3.1新增静态目录(包)static,用于存放bootstrap,在settings.py中增加static的设置

3.2复制bootstrap到static目录中

4.由于数据库中暂时没有数据,所有,下面,进行'新增图书'的设计.

4.1建立'新增图书的'路由设置

4.2建立'新增图书'的视图创建

4.3创建'新增图书'的模板,注意在表单部分的最前面增加{%csrf_token%},防止跨域403错误

模板注意使用class="container"制作外框,class="row"class="col-md-6col-lg-push-3(右移3)"建立模型

5.所有'图书'信息查看的设计,基本步骤和4一致.注意图书出版日期的显示{{book.pub_date|date:'Y-m-d'}}

6.'删除'功能.注意.注意路由设计re_path(r'books/(\d+)/delete/',views.delbook),

7.修改功能,注意点和6一样

8.完整代码:

51.1多表,为啥要用多个表

避免存储大量重复数据.把大表拆成多个表.

51.2一对多表,一个出版社对应多本书.

51.3总结:一旦确定表关系是一对多:创建关联字段,上图的publish_id是关联字段,创建关联字段要在多的表中

52.1多对多表,一本书对应多个作者,一个作者对应多本书.

52.2总结:一旦确定表关系是多对多:要创建第三张关系表,如上图Book2Author

53.1一对一表,本质是把一张表中的几个字段抽离出来组建一个新表.

一对多与一对一的差别.一对一的关联字段加上unique约束.关联字段放在哪张表都可以.

53.2总结:一旦确定是一对一的关系:在两张表中的任意一张表中建立关联字段+unique

建关联关系是为了查询,建约束关系是为了维护数据的完整.

约束关系存在的目的,删除被关联表的一条数据,如果两表只有关联字段,无约束关系,则会直接删除.如果有约束关系,则无法直接删除,会有提示,无法删除.

如上表,如果删除publish表中的第1条数据,则再查下时将无法查出php书籍的出版社信息.所以增加了约束关系,使得操作者无法随意删除.

若只有关联关系而无约束关系,就可以直接删除.

上图的publsish_id字段是两表的关联字段,上图的foreignkey就是建立约束关系

THE END
1.特殊网名制作软件大全网名app下载网名生成器特殊网名制作软件大全能生成带有特殊符号昵称的软件,比如竖立网名、稀有漂亮符号、麒麟符号、昵称中间一横等特殊符号,非常独特好看,一键即可生成你想要的特殊符号昵称,网名生成器、特殊网名制作、网名大全等软件让你在众多不同的社交网络平台上都是非常适用的,大家可以生成自己专属的网名,结合创意和符号等等,可以让你的文字http://www.downyi.com/key/wangmingzhizuoruanjian/
2.名字随机生成器——让你快速取名在生活中,取名是一项非常重要的任务,名字的好坏将会对你的生活产生很大的影响。但是取好名字并不是一件容易的事情,有的人会花费很长时间才能想出一个满意的名字。为了解决这一问题,今天我们就来介绍一种名字生成器——名字随机生成器。 名字随机生成器是一款非常实用的工具,可以帮助你快速生成适合你的名字。该工具https://www.bamuwu.com/details/2064
3.在线八字易经宝宝取名源码带源码数据(网页+APP+小程序)自然语言处理技术:如分词、词性标注、命名实体识别等,这些技术可以用于名字寓意的解析和生成。 开发工具 开发工具用于辅助开发过程,提高开发效率。在起名源码中,常用的开发工具包括: 版本控制系统:如Git等,用于代码的版本管理和协作开发。 IDE(集成开发环境):如Visual Studio Code、PyCharm等,这些IDE提供了代码编辑、调https://blog.csdn.net/rongtinghua/article/details/144259476
4.在线签名生成器免费,rpa,机器人,自动化艺术签名设计免费版在线生成艺术签名在线生成器2024年9月9日?·?艺术签名在线生成器使用非常方便,只需输入你的名字并选择款式就可以一键生成了,完全免费,不限制次数,你可以完全自由发挥. 最高支持四个字的中文名字设计,如果是 更多内容请查看http://www.kachayv.cn/https://www.wdlinux.cn/html/email/20241211/23845.html
5.[社区]制作一个简单的随机姓名(内附一键粘贴)·GameCreatorGame.player.variable.setString(14002,生成.first() ); 复制 显示全部 复制 之后我们设置一下字符串,让全名=姓+名 点击事件就做完了,你的随机姓名也会存进去 什么你问我确认是干嘛的,那个是关闭界面 咱来运行一下 成功了 如果你想姓和名字分开roll,那就做两个按钮,然后把上面的内容复制对应部分,其实很好分https://www.gamecreator.com.cn/forum/det/3850
6.创作猫全国重名查询,详细教程,简单制作,日入多张创作猫的基础功能:去水印、智能配音、老照片修复等,想必大家都有耳闻。 但是却很少有人知道创作猫还有强大的变现板块:涵盖了小说推文、短剧推广、小程序测试等多种内容。 我之前给侄女取名在网上找灵感,刷视频的时候发现一个全国重名查询的小程序,今天就拆解这个项目的玩法 http://www.hmly8.com/?p=59819
7.创作猫全国重名查询,详细教程,简单制作,日入多张创富道场【vip1188.cn】项目课程资源网:创作猫全国重名查询,详细教程,简单制作,日入多张【揭秘】 创作猫的基础功能:去水印、智能配音、老照片修复等,想必大家都有耳闻。 但是却很少有人知道创作猫还有强大的变现板块:涵盖了小说推文、短剧推广、小程序测试等多种内容。 我之前给侄女取名在网上找灵感,刷视频的时候发https://vip1188.cn/35347.html
8.创作猫全国重名查询,详细教程,简单制作,日入多张创作猫的基础功能:去水印、智能配音、老照片修复等,想必大家都有耳闻。 但是却很少有人知道创作猫还有强大的变现板块:涵盖了小说推文、短剧推广、小程序测试等多种内容。 我之前给侄女取名在网上找灵感,刷视频的时候发现一个全国重名查询的小程序,今天就拆解这个项目的玩法 https://www.midou55.com/79767.html
9.花草名称生成器生成字体分类发现字体简介: 花草名称生成器 Shitzu&Porko_PersonalUseOnly 语言:英文 下载 Novelin Black Italic 语言:英文 下载 SherilynSANS 语言:英文 下载 Liber Grotesque Family Thin 语言:英文 下载 Vicanza 语言:英文 下载 PrincessCards 语言:英文 下载 HumbleNostalgia-Italic 语言:英文 下载 FSP DEMO - Octin Prisonhttp://www.qiuziti.com/fontlist2?id=1041628
10.英文名字在线生成在线生成SDK代码华为云帮助中心为你分享云计算行业信息,包含产品介绍、用户指南、开发指南、最佳实践和常见问题等文档,方便快速查找定位问题与能力成长,并提供相关资料和解决方案。本页面关键词:英文名字在线生成。https://support.huaweicloud.com/topic/212170-1-Y
11.姓名代码在线转换器理想股票技术论坛姓名代码在线转换器是一款方便快捷的工具,能够将中文姓名转换成对应的名称代码或代码转换为中文姓名。使用该转换器可以帮助用户快速查询和查找相应的姓名代码,方便实现个人信息录入、数据处理等操作。无论是需要进行批量转换还是单个转换,该转换器都能够满足用户的需求,https://www.55188.com/tag-3650810.html
12.芋道框架万字详解(前后端分离)若依框架yudao可以看出来芋道开发框架是非常全能的,我也用这个框架开发了三个项目所使用的技术栈后端为SpringCloud,前端使用的是Vue3,数据库主要用的两个,MySQL和postgre,主要使用的是他的代码生成功能,在此需要注意的是芋道开发框架目前只支持MySQL的建表插入语句,其余数据库需要另做更改,我一会会去介绍postgre的使用方式。 https://developer.aliyun.com/article/1576332
13.全网首发,4万字Instagram从0到1流量变现实操手册Instagram名字源自于Instamatic,是柯达从1963年开始销售的一个相机的系列名。 公司位于旧金山,由Kevin Systrom动态会展示你在Instagram上登录过的网址链接和你的在线时长。 2.4 成效分析 Insights Aa该功能以文字形式展现,系统为你生成一张贺卡、动图,以用户互动为目的。 系统会给你推荐背景模板,点击https://www.360doc.cn/article/74163855_1125552299.html
14.微信透明昵称设置,空白名字代码生成教程手机堂1、在公众号手机堂后台回复数字5或者“空白昵称”,会得到一个空白的代码符号 。 2、长按复制空白昵称代码。 3、打开微信进入-我-点击自己头像,进入资料设置页面,把空白符号粘贴到名字一栏,然后点击保存就可以了。 返回对话框打开自己头像刷新一下资料,看看是不是变成空白了,这样就搞定了。 https://www.163.com/dy/article/HD0BIE310511K7NK.html
15.抖音空白昵称()(抖音空白昵称代码复制)只需要输入关键词,就能返回你想要的内容,有小程序、在线网页版、PC客户端和批量生成器 官网:https://ai.de1919.com。 本文目录: 抖音名叫空白昵称什么意思 抖音个人简介怎么空白 抖音空白昵称代码复制 抖音名叫空白昵称什么意思 抖音昵称为空说明这个人是用手机登陆上的抖音,上去之后一直没有给自己在抖音上起https://www.de1919.com/article/580456.html
16.微信昵称怎么设置空白微信空白名字代码接亲网微信昵称怎么设置空白 微信空白名字代码 微信,一款即时跨平台通讯工具,可支持单人,多人在线,给大家提供了不少的便利。里面的功能繁多,可供大家选择也是经常要使用到的东西。但是想必大家也晓得,在每一个社交平台上都会有像现实世界中的名片一样的东西—网名或昵称,有了它,相当于有个代号,最起码别人晓得你是谁,那么https://www.jieqinwang.com/baike/52282.html
17.空白代码复制微信名字游戏3、点击“安卓转换”,之后点击“复制”,返回微信“发现”界面,点击右下角“我”,点击“个人头像”,点击“昵称”,删除原来的昵称,长按复制后,点击右上角“保存”即可。 二、微信空白名字代码 之一步、复制特殊符号,不是一般的空白格式 ,直接打空格是没有用的必须用下面的符号,大家可以直接复制:() https://www.taofang114.com/post/17806.html
18.id单字生成器(单字id转换器)游戏问答一个字的ID其实不值钱id单字生成器,因为可以添加【空白代码】这种字符id单字生成器,比如id单字生成器你打算取“帅”这一个字的名字,取名格式就是【空白字符+帅+空白字符】这样,只要不和别人取过的空白字符格式重复,就能成功修改。 第一种为利用游戏BUG;如之前的改名卡BUG,可以输入空格字符。第二种为利用系统识别https://www.fkw8.com/ask/4990.html
19.空白符号,空白名字制作,空白代码复制,王者荣耀CF吃鸡空白名字生成器王者荣耀空白符号,空白代码,空白网名,王者荣耀空白名字,王者空白名,王者空白名怎么打,空白名字复制,王者荣耀CF吃鸡空白名字生成器http://kongbai.teshufuhao.cn/
20.考生姓名代码在线查询昌1893 猖1894 场1901 尝1902 常1903 长1904 偿1905 肠1906 厂1907 敞1908 畅1909 唱1910 倡1911查询员工表显示员工名字、编号、工资,查询结果以名字为序升序排列 2.查询员工表显示员工名字、编号、CAD图案代码查询 免费文档中心 免费文档中心可免积分在线阅读和下载文档 ?免费文档 ?高等教育 ?高中教育https://m.360docs.net/doc/a113248378.html
21.WordPress引用阿里巴巴矢量图标库添加彩色图标第三步:跳转到我的项目页面(没有跳转的点击–>资源管理–>我的项目)//我的项目自己创建名字 第四步:在我的项目页面有一下按钮—>一般选Symbol 第五步:点击 –>查看在线链接(没有的的话可以点击生成链接) —>点此复制代码(代码例如下面) 代码语言:javascript https://cloud.tencent.com/developer/article/2335425
22.cf空白名字制作生成软件下载散人CF空白名代码生成器v1.0免费绿色版由恋伤制作的cf散人空白名称生成器可以随机生成15000千种不同空白呢称,如生成空白名已被使用,您可以点击重新生成空白名按钮或选择自动生成空白名,知道更改名字成功为止,在自动模式下,将每隔10秒钟自动更换一次空白名并复制至剪切板。 代码生成器空白名CF散人 https://www.jb51.net/game/704145.html
23.在线姓名自动生成器注:长宽可以调整。 在自定义姓氏里输入你的姓氏,N多名字任你选~ 代码:<EMBED height=430 type=application/x-shockwave-flash pluginspage=http://www.macromedia.com/go/getflashplayer width=700 src=http://sm./fl/qiming.swf wmode="transparent" invokeurls="false" quality="high" allowScriptAccess="nevehttp://www.360doc.com/content/12/1007/15/6085160_240040489.shtml