模块6Django考核知识点
# 第十二章主要内容
```
1、Web框架原理剖析
2、Web请求生命周期剖析
3、开发一个简单的Web框架
4、MTV\MVC框架介绍
5、Django框架基本使用
6、路由系统url,精确匹配、模糊匹配、url分组
7、视图views、Function based views和Class based views
8、get\post请求处理
9、通过Template模板语言返回动态数据到前端页面
10、Template tags使用
11、HttpResponse、render、redirect等方法使用
12、Django orm介绍,models定义语法,SQL增删改查语句使用
13、Foreign key,many to many,字段类型讲解
14、将models同步到数据库
```
###一、问答题
1、Web框架的本质是什么?为什么要有Web框架?
Web应用本质上就是一个socket服务端,而用户的浏览器就是一个socket客户端。 Web框架(Web framework)是一种开发框架,用来支持动态网站、网络应用和网络服务的开发。这大多数的web框架提供了一套开发和部署网站的方式,也为web行为提供了一套通
用的方法。web框架已经实现了很多功能,开发人员使用框架提供的方法并且完成自己的业务逻辑,就能快速开发web应用了。浏览器和服务器的是基于HTTP协议进行通信的。也可以
说web框架就是在以上十几行代码基础上扩展出来的,有很多简单方便使用的方法,大大提高了开发的效率。
2、请描述一个客户端请求从发起到返回的过程(用django来描述);
1. 用户通过浏览器请求一个页面 2.请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求 3.URLConf通过urls.py文件和请求的URL找到相应的View 4.View Middlewares被访问,它同样可以对request做一些处理或者直接返回response 5.调用View中的函数 6.View中的方法可以选择性的通过Models访问底层的数据 7.所有的Model-to-DB的交互都是通过manager完成的 8.如果需要,Views可以使用一个特殊的Context 9.Context被传给Template用来生成页面 a.Template使用Filters和Tags去渲染输出 b.输出被返回到View c.HTTPResponse被发送到Response Middlewares d.任何Response Middlewares都可以丰富response或者返回一个完全不同的response e.Response返回到浏览器,呈现给用户
3、请解释你对MTV和MVC架构的理解?
MVC(Model View Controller 模型-视图-控制器) 是一种Web架构的模式。特点:把业务逻辑、模型数据、用户界面分离开来,让开发者将数据与表现解耦。 Model: 代表数据存取层, View 代表的是系统中选择显示什么和怎么显示的部分, Controller 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。 MTV(Model Templates View 模型-模板-视图): 1.Models:数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效,是一个抽象层,用来构建和操作你的web应用中的数据,模型是你的数据的唯一的、权威的
信息源。它包含你所储存数据的必要字段和行为。通常,每个模型对应数据库中唯一的一张表。 2.模板(templates):即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。模板层提供了设计友好的语法来展示信息给用户。使用模板方法可以动态地
生成HTML。模板包含所需HTML 输出的静态部分,以及一些特殊的语法,描述如何将动态内容插入。 3.视图(views):业务逻辑层,该层包含存取模型及调取恰当模板的相关逻辑。用于封装负责处理用户请求及返回响应的逻辑。视图可以看作是前端与数据库的中间人,他会将前端想
要的数据从数据库中读出来给前端。他也会将用户要想保存的数据写到数据库。 区别: MVC中的View的目的是「呈现哪一个数据」,而MTV的View的目的是「数据如何呈现」。 也就是把MVC中的View分成了视图(展现哪些数据)和模板(如何展现)2个部分,而Contorller这个要素由框架自己来实现了,我们需要做的就是把(带正则表达式的)URL对应到视
图就可以了,通过这样的URL配置,系统将一个请求发送到一个合适的视图。
4、请写出创建一个*Django project*的命令;
django-admin.py startproject mysite
5、请写出创建一个*Django app*的命令;
python manage.py startapp blog
6、请问*Django project*和*Django app*之间有什么区别和联系?
一个Django项目就是一个基于Django的Web应用。 一个Django项目中包含一组配置和若干个Django应用。 一个Django应用就是一个可重用的Python软件包,提供一定的功能。 一个Django应用中可以包含models, views, templates, template tags, static files, URLs等。 一个Django项目可以包含多个Django应用。 一个Django应用也可以被包含到多个Django项目中,因为Django应用是可重用的Python软件包。
7、什么是WSGI?为什么我们需要WSGI?
WSGI的全称是Web Server Gateway Interface,翻译过来就是Web服务器网关接口。具体的来说,WSGI是一个规范,定义了Web服务器如何与Python应用程序进行交互,
使得使用Python写的Web应用程序可以和Web服务器对接起来。 WSGI协议(通讯协议):Python用于Web开发的协议(用于处理Web服务器和应用程序(APP)的交互信息) (把http通讯的过程抽象出来(请求数据,响应数据的封装),开发者只负责处理中途的数据)
8、HTTP协议有哪些请求?请分别介绍他们;
1.GET GET可以请求指定的页面,并且返回网站的实体。 2.HEAD HEAD和GET请求很相似,只不过是不能返回具体的内容,主要是用于获取报头。 3.POST POST是像之指定的数据进行发送请求,在网站中,可能会有一些表单的和文件的上传,当数据包含在请求当中,POST请求就会导致一些数据的变动和修改。 4.PUT PUT是指从客户端向服务器传送数据,并且把一部分的数据进行取代。 5.DELETE DELETE是指送到到服务器要求删除指定的页面。 6.CONNECT CONNECT是指预留给可以连接改为管道的服务器。 7.OPTIONS OPTIONS是请求是可以允许客户看服务器的性能。 8.TRACE TRACE主要是用于测试,并且返回一些服务器的请求。
9、请详细说明Django中间件处理请求的流程(各个处理函数的执行顺序);

10、描述你所知道的 django 常用命令, 并说下它们分别是作什么的 (e.g python manage.py shell (django项目环境终端));
新建一个 django project django-admin.py startproject project-name 新建 app python manage.py startapp app-name 创建数据库表 或 更改数据库表或字段 python manage.py makemigrations python manage.py migrate 使用开发服务器 python manage.py runserver python manage.py runserver 9999 创建超级管理员 python manage.py createsuperuser
11、请问django中如何进行路由分发操作?
路由配置都是在项目的全局控制文件(项目名称目录下的urls.py)
path('admin/', admin.site.urls),
path('index/', views.index, name="indexx"),
path('login/', views.login),
12、url中什么是无命名传参和有命名传参, 请说明如何添加额外的参数?
无名分组
-按位置传参
-分组之后,会把分组出来的数据,当位置参数,传到视图函数,所以,视图函数需要定义形参
-url(r'^publish/([0-9]{4})/([0-9]{2})$', views.publish),
-def publish(request,*args): 视图函数可以这样接收
有名分组
-按关键字传参
-有名分组之后,会把分组出来的数据,当关键字参数,传到视图函数,所以,视图函数需要定义形参,形参名字要跟分组的名字对应,与顺序无关
-url(r'^publish/(?P<year>[0-9]{4})/(?P<mounth>[0-9]{2})/$', views.publish),
-def publish(request, mounth,year):
*****有名分组和无名分组,不要混用
13、一条url映射的view可以对应多个http请求操作吗?
可以
14、django2.0 路由中的re_path和path的区别是什么?
re_path是正则路由 path是非正则路由
15、url反向解析使用的函数是什么, 需要配置什么?
reverse()函数
本质上就是给url匹配模式起别名,然后用过别名拿到具体的URL路径
1. 怎么起别名?
在url匹配模式中,定义name="别名"
2. 如何使用?
1. 在模板语言里面使用:
{% url "别名" %} --> 得到具体的URL路径
2. 在视图中如何使用:
from django.urls import reverse
reverse("别名") --> 得到具体的URL路径
3. 如何传参数?
1. 模板语言中:
{% url "别名" 2018 "nb" %}
2. 视图函数中
传位置参数:
reverse("别名", args=(2018, "nb"))
传关键字参数:
reverse("别名" kwargs={"year": 2018, "title": "nb"})
16、url中命名空间namespace可以起到什么作用?
为了防止不同的app下面的url匹配模式有重复的别名
17、视图中处理请求的方式有几种?
FBV 和 CBV 模式 FBV fbv就是在url中一个路径对应一个函数 CBV cbv就是在url中一个路径对应一个类
18、请介绍视图中的请求(request)和响应(response)对象;
request的属性
django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。 除了特殊说明的之外,其他均为只读的。
1.HttpRequest.GET
一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。
2.HttpRequest.POST
一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。
POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。
因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST"
另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。
注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:
request.POST.getlist("hobby")
3.HttpRequest.body
一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。
但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。
4.HttpRequest.path
一个字符串,表示请求的路径组件(不含域名)。
例如:"/music/bands/the_beatles/"
5.HttpRequest.method
一个字符串,表示请求使用的HTTP 方法。必须使用大写。
例如:"GET"、"POST"
6.HttpRequest.encoding
一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。
这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。
接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。
如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。
7.HttpRequest.META
一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:
CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。
HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。
REMOTE_HOST —— 客户端的主机名。
REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。
SERVER_PORT —— 服务器的端口(是一个字符串)。
从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,
都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。
所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。
8.HttpRequest.FILES
一个类似于字典的对象,包含所有的上传文件信息。
FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。
注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会
包含数据。否则,FILES 将为一个空的类似于字典的对象。
9.HttpRequest.COOKIES
一个标准的Python 字典,包含所有的cookie。键和值都为字符串。
10.HttpRequest.session
一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
完整的细节参见会话的文档。
11.HttpRequest.user(用户认证组件下使用)
一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。
如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。
request常用方法
1.HttpRequest.get_full_path()
返回 path,如果可以将加上查询字符串。
例如:"/music/bands/the_beatles/?print=true"
2.HttpRequest.is_ajax()
如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。
大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。
如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。
视图响应对象
HttpResponse响应体
1.HttpResponse():
HttpResponse括号内直接跟一个具体的字符串作为响应体,比较直接很简单,所以这里主要介绍后面两种形式。
2.render():
render(request, template_name[, context])
给定一个给定的模版和一给定的上下文字典,并返回一个渲染后的HttpResponse对象。
例如:
render(request,‘index.html’,{"ctime_key":ctime})
相对应的html文件:
<h1>{{ ctime_key }}</h1> # 任意标签
3.redirect()
传递要重定向的一个硬编码的URL
def my_view(request):
...
return redirect('/some/url/')
也可以是一个完整的URL
def my_view(request):
...
return redirect('http://example.com/')
19、什么是orm?
MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
ORM是“对象-关系-映射”的简称。
如果进行数据库迁移,不同数据库的sql语句是有差别的,而ORM是上层封装,只需按照指定的数据库引擎就可以翻译为相对应的sql语句,便于数据库迁移。但是它的效率不高。
不需要调用mysql,django的上层封装;它只能做到表这一层
sql表----->python的 类
字段------>类的属性
表记录---->python类对象
20、modules创建模型变化迁移和模型变化到数据库的命令是什么?
python manage.py makemigrations python manage.py migrate
21、谈谈你对Django models通过类映射数据库表的理解;
22、多对多关系中的第三张表,也就是关系表如何创建?
一对一就是oneToOneField;一对多就是ForeignKey;它俩是一样的,会在那张表里边多生成一个字段,加一个_id+一个约束关系;多对多就是ManyToManyField,会生成一个第三张关系表; authors = models.ManyToManyField(to="Author")
23、请介绍你了解的字段类型(e.g CharField );
```
AutoField #An IntegerField that automatically increments according to available IDs
BigAutoField #A 64-bit integer, guaranteed to fit numbers from 1 to 9223372036854775807.
BigIntegerField #-9223372036854775808 to 9223372036854775807
BinaryField #A field to store raw binary data. It only supports bytes assignment
BooleanField
CharField
DateField #e.g 2019-04-27
DateTimeField #e.g 2019-04-27 17:53:21
DecimalField
DurationField #storing periods of time ,e.g [DD] [HH:[MM:]]ss[.uuuuuu]"
EmailField
FileField #存储文件
FloatField
ImageField #Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.
IntegerField
GenericIPAddressField #IP地址,支持ipv4
NullBooleanField #Like a BooleanField, but allows NULL as one of the options
PositiveIntegerField #Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647
PositiveSmallIntegerField #only allows positive values from 0 to 32767
SlugField # A slug is a short label for something, containing only letters, numbers, underscores or hyphens.
SmallIntegerField
TextField #A large text field.
TimeField #A time, represented in Python by a datetime.time instance.
URLField
UUIDField #A field for storing universally unique identifiers. Uses Python’s UUID class.
```
24、针对关系型数据库提供的关系操作字段分别是什么?
OneToOneField:一对一,将字段定义在任意一端中 ForeignKey:一对多,将字段定义在多的一端中 ManyToManyField:多对多,将字段定义在两端中
25、请问如何自定制字段?
```
(详情文档参见: https://docs.djangoproject.com/en/2.0/howto/custom-model-fields/)
```
26、通过定义内部类Meta, 可以添加哪些参数(e.g, unique_together), 作用分别是什么?
Meta选项 Django模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性。而可用的选项大致包含以下几类 abstract 这个属性是定义当前的模型是不是一个抽象类。所谓抽象类是不会对应数据库表的。一般我们用它来归纳一些公共属性字段,然后继承它的子类可以继承这些字段。 Options.abstract 如果abstract = True 这个model就是一个抽象类 app_label 这个选型只在一种情况下使用,就是你的模型不在默认的应用程序包下的models.py文件中,这时候需要指定你这个模型是哪个应用程序的。 Options.app_label 如果一个model定义在默认的models.py,例如如果你的app的models在myapp.models子模块下,你必须定义app_label让Django知道它属于哪一个app app_label = ‘myapp’ db_table db_table是指定自定义数据库表明的。Django有一套默认的按照一定规则生成数据模型对应的数据库表明。 Options.db_table 定义该model在数据库中的表名称 db_table = ‘Students’ 如果你想使用自定义的表名,可以通过以下该属性 table_name = ‘my_owner_table’ db_teblespace Options.db_teblespace 定义这个model所使用的数据库表空间。如果在项目的settin中定义那么它会使用这个值 get_latest_by Options.get_latest_by 在model中指定一个DateField或者DateTimeField。这个设置让你在使用model的Manager上的lastest方法时,默认使用指定字段来排序 managed Options.managed 默认值为True,这意味着Django可以使用syncdb和reset命令来创建或移除对应的数据库。默认值为True,如果你不希望这么做,可以把manage的值设置为False order_with_respect_to 这个选项一般用于多对多的关系中,它指向一个关联对象,就是说关联对象找到这个对象后它是经过排序的。指定这个属性后你会得到一个get_xxx_order()和set_xxx_order()的方法,通过它们你可以设置或者回去排序的对象 ordering 这个字段是告诉Django模型对象返回的记录结果集是按照哪个字段排序的。这是一个字符串的元组或列表,没有一个字符串都是一个字段和用一个可选的表明降序的’-‘构成。当字段名前面没有’-‘时,将默认使用升序排列。使用’?'将会随机排列 ordering=[‘order_date’] # 按订单升序排列 ordering=[’-order_date’] # 按订单降序排列,-表示降序 ordering=[’?order_date’] # 随机排序,?表示随机 ordering=[’-pub_date’,‘author’] # 以pub_date为降序,在以author升序排列 permissions permissions主要是为了在Django Admin管理模块下使用的,如果你设置了这个属性可以让指定的方法权限描述更清晰可读。Django自动为每个设置了admin的对象创建添加,删除和修改的权限。 permissions = ((‘can_deliver_pizzas’,‘Can deliver pizzas’)) proxy 这是为了实现代理模型使用的,如果proxy = True,表示model是其父的代理 model unique_together unique_together这个选项用于:当你需要通过两个字段保持唯一性时使用。比如假设你希望,一个Person的FirstName和LastName两者的组合必须是唯一的,那么需要这样设置: unique_together = ((“first_name”, “last_name”),) 一个ManyToManyField不能包含在unique_together中。如果你需要验证关联到ManyToManyField字段的唯一验证,尝试使用signal(信号)或者明确指定through属性。 verbose_name verbose_name的意思很简单,就是给你的模型类起一个更可读的名字一般定义为中文,我们: verbose_name = “学校” verbose_name_plural 这个选项是指定,模型的复数形式是什么,比如: verbose_name_plural = “学校” 如果不指定Django会自动在模型名称后加一个’s’
27、请写出在django中如何获取请求的数据,分别写出get和post的获取方式;
request.method == 'GET' request.method == 'POST'
28、all、filter、exclude方法有什么区别?
all():返回所有数据。 filter():返回满足条件的数据。 exclude():返回满足条件之外的数据。
29、get和filter操作出的结果集是什么数据类型, 有什么区别?
get返回值是一个定义的model对象,get只有一条记录返回的时候才正常,也就说明get的查询字段必须是主键或者唯一约束的字段。当返回多条记录或者是没有找到记录的时候都会抛出异常。 filter返回值是一个新的QuerySet对象,然后可以对QuerySet在进行查询返回新的QuerySet对象,支持链式操作。QuerySet一个集合对象,可使用迭代或者遍历,切片等,但是不等于list类型,filter的参数可以是字段,也可以是扩展的where查询关键字,如in,like等,filter有没有匹配记录都可以。
30、create和save方法有什么区别?
用save方法创建对象 用save方法创建一个名叫john的具体对象,我们可以这么做。记住你只有用了save()方法后,Django才会将这个对象的信息存储到数据库中。 john = Person(name="John Fourkas") john.save() 用create方法创建对象 正因为用save方法创建对象有2步,而且编程人员容易忘记加上save(),Django提供了一个更便捷的create方法,如下。如果你使用create方法,无需再加上save()。create方法不仅创建了新的对象,而且直接将信息存储到数据库里。 john = Person.objects.create(name="John Fourkas") save与create方法比较 create只能用于创建新的对象,在数据库层总是执行insert的操作。save不仅用于创建新的对象,也能用于更新对象的现有数据,在数据库层总是先执行update,找不到具体对象后再执行insert的操作。对于创建全新的对象,两者都可以。如果更新已有对象信息,只能用save()方法
31、ORM批量创建使用哪个方法, for循环去创建多条记录, 哪种更高效?
批量插入数据
批量插入数据的时候,首先要创建一个对象的列表,然后调用bulk_create方法,一次将列表中的数据插入到数据库中。
product_list_to_insert = list()
for x in range(10):
product_list_to_insert.append(Product(name='product name ' + str(x), price=x))
Product.objects.bulk_create(product_list_to_insert)
32、ORM如何保存 `外键` 和 `多对多` 字段
ForeignKey(to="类名",related_name=“xx”) --> 1对多 ,外键通常设置在多的那一边、 ManyToMany(to="类名",related_name="xx") --> 多对多,通常设置在正向查询多的那一边
33、QuerySet切片映射到数据库sql对应什么操作?
limit
34、排序使用什么方法, 正序、倒序, 分别使用什么参数?
正序排列的方法:【models对象.objects.order_by(“字段名")】
report.objects.order_by("endtime")
倒序排列的方法:【models对象.objects.order_by(“-字段名")】
report.objects.order_by("-endtime")
35、QuerySet 支持查询的api(大约有24种) 分别有什么并指出它们的含义?例如: field `field_name__exact`, `field_name__endswith` 至少描述10种以上
#(1)all方法,查出所有结果。返回值是一个queryset对象,支持序列对象。
#book_list = Book.objects.all()
#print(book_list) #[obj,obj1,obj2,,,] #直接打印类的对象是一个object的一个结果如下,你可以在类里边加一个def __str__(self)
#<QuerySet [<Book: Book object (1)>,Book:Book object (2)>]> # return self.title #这时候它就会打印它的title属性了
#<QyertSet [<Book: python>, <Book: php>]>
# for obj in book_list: #支持for循环
# print(obj.title, obj.price)
#print(book_list[1].title) #支持索引、切片。
#(2)first,last;调用者为queryset对象,返回值为models对象 (<class ‘app01.models.Book’>)
#book = Book.objects.all().first() #拿到第一个models模型对象
#book = Book.objects.all()[0] #跟上边是一个意思。
#(3)filter() 返回值queryset对象 对比下filter和all;filter是拿到筛选条件的结果,all是拿到所有的结果。
# book_list = Book.objects.filter(price=100) #[obj,obj1,obj2...]
# print(book_list) #<QuerySet [<Book: python红宝书>, <Book: php>]>
# book_obj = Book.objects.filter(price=100).first()
#SQL---> SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`pub_date`, `app01_book`.`price`, `app01_book`.`publish` FROM `app01_book` WHERE `app01_book`.`price` = 100 LIMIT 21;
# ret = Book.objects.filter(title="go", price=200) #filter也可以加多个查询条件,这两个条件缺一不可。
# print(ret) #<QuerySet []>
#(4)get() 有且只有一个查询结果时才会拿出来,才会有意义,否则会报错 返回值:model对象
# book_obj = Book.objects.get(title="go")
# book_obj = Book.objects.get(title="price") #会报错哦
# print(book_obj.price)
SQL---> SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`pub_date`, `app01_book`.`price`, `app01_book`.`publish` FROM `app01_book` WHERE `app01_book`.`title` = 'php';
#(5)exclude() 返回值:queryset对象
#ret = Book.objects.exclude(title="go") #除了title="go"的书籍全部给过滤出来。 排除条件过滤,filter是按照条件过滤
#print(ret) #<QuerySet [<Book: python红宝书>, <Book: php>]>
SQL---> SELECT `app01_book`.`id`, `app01_book`.`title`, `app01_book`.`pub_date`, `app01_book`.`price`, `app01_book`.`publish` FROM `app01_book` WHERE NOT (`app01_book`.`title` = 'go') LIMIT 21;
#(6)order_by() 调用者queryset对象; 返回值queryset对象
#ret = Book.objects.all().order_by("id") #从小到大
#ret = Book.objects.all().order_by("-id") #从大到小
#ret = Book.objects.all().order_by("price")#按照价格大小排序
#ret = Book.objects.all().order_by("price", "id") #组合,当价格一样了就用id排序
#print(ret)
#(7)count() 调用者queryset对象,返回值int
# ret = Book.objects.all().count() #SQL--->> SELECT COUNT(*) AS `__count` FROM `app01_book`;
# print(ret) #3
#(8)exist() 问是否存在
# ret = Book.objects.all().exists() 不要把所有数据都取出来,这样效率很慢。.exists下其实是取的是LIMIT 1(对应的sql语句)
# if ret:
# print("ok")
#(9)values方法 调用者queryset对象,返回值queryset
# ret = Book.objects.all() #想拿到所有书籍的名称。
# for i in ret:
# print(i.tittle) #并不想拿对象,想拿对象里的某个字段
#ret = Book.objects.all().values("price", "title") #values()你想拿的字段。去掉all()也是一样的,.values就是.all()了;可以只加一个price的值。
'''
values的原理:
temp=[]
for obj in Book.objects.all()
temp.append({
"price"=obj.price
"title"=obj.title
})
return temp
'''
#print(ret) #列表里边放字典
#<QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('100.00')}, {'price': Decimal('250.00')}]> #跟之前的QuerySet有区别,;列表里边放的不是一个个对象了而是个字典,把对象取出来的值作为键值对放在字典里;查询到几个对象就有几个字典。
#print(ret[0].get("price")) #100.00
#(10)values_list方法 调用者queryset对象,返回值queryset
#ret = Book.objects.all().values_list("price", "title")
#print(ret) #一个字典被换成元组了,列表里边放元组了,把字典的值去掉了,元组光有值。
#<QuerySet [(Decimal('100.00'), 'python红宝书'), (Decimal('100.00'), 'php'), (Decimal('250.00'),'go')]>
'''values_list和values的区别:一个是字典、一个是元组;
values: <QuerySet [{'price': Decimal('100.00'), 'title': 'python红宝书'}, {'price': Decimal('100.00'), 'title': 'php'}, {'price': Decimal('250.00'), 'title': 'go'}]>
values_list <QuerySet [(Decimal('100.00'),'python红宝书'), (Decimal('100.00'), 'php'), (Decimal('250.00'), 'go')]>
'''
#(11) distinct(去重)
#ret = Book.objects.all().distinct() #这样写没有意义,把它们都distinct了,distinct一个有重复的字段才会有意义
#print(ret)
#ret = Book.objects.all().values("price") # SQL ---> SELECT `app01_book`.`price` FROM `app01_book` LIMIT 21;
#print(ret) #<QuerySet [{'price': Decimal('100.00')}, {'price':Decimal('100.00')}, {'price': Decimal('250.00')}]>
ret = Book.objects.all().values("price").distinct() #SQL---> SELECT DISTINCT `app01_book`.`price` FROM `app01_book` LIMIT 21;
print(ret) #<QuerySet [{'price': Decimal('100.00')}, {'price': Decimal('250.00')}]>
36、如何跨表操作?
跨表查询: 基于对象查询; 基于双下划线查询; 聚合与分组查询 F 与 Q 查询
正向查询按字段,反向查询按表名
37、过滤器(`filter`, `get`) 提供别的定制操作(复杂查找)
1) 使用添加、减法、乘法、除法、模块和幂运算,使用F()对象
from django.db.models import F
2) 如何在过滤器中提供 `与` `或` `非` 操作
from django.db.models import Q "不等于" myapps = App.objects.filter(~Q(name= '')) "或" myapps = App.objects.filter(Q(name = 'alex')|Q(name = 'yuan'))
38、QuerySet提供了缓存机制, 避免重复连接数据库的查询.
1) models.Entry.objects.all() 此条 orm 操作会去查询数据库吗?
2) ORM 切片操作
>>> queryset = Entry.objects.all()
>>> print(queryset[5]) # Queries the database
>>> print(queryset[5]) # Queries the database again
>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # Queries the database
>>> print(queryset[5]) # Uses cache
>>> print(queryset[5]) # Uses cache
39、`django` 中如何在 `model` 保存前做一定的固定操作,比如写一句日志?
利用Django的Model的Signal Dispatcher, 通过django.db.models.signals.pre_save() 方法,在事件发生前,发射触发信号,这一切都被调度中的receiver方法深藏功与名的保存了。
信号的处理一般都写在Model中,举个例子:
import logging
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
class Order(models.Model):
# ...
logger = logging.getLogger(__name__)
@receiver(pre_save, sender=Order)
def pre_save_handler(sender, **kwargs):
# 我们可以在Order这个Model保存之前尽情调戏了:)
logger.debug("{},{}".format(sender, **kwargs))
print 'fuck universe'
这样应该就实现了题中的要求,类似的方法还有比如 pre_init 是在Model实例之前会触发, post_init 在实例之后触发,同理就是 pre_save 和 post_save 了。
40、请描述 `django` 中 settings 机制;
41、QuerySet 提供的性能相关的方法有哪些, 例如 `select_related` 和 `prefetch_related` 它们的区别是什么
42、if queryset.exists 和 if queryset 那种效率更高效?
43、queryset.count() 和 len(queryset) 那种效率更高效?
44、queryset中提供了执行原生 sql 的 api 是哪些方法?
一:extra:结果集修改器,一种提供额外查询参数的机制
二:raw:执行原始sql并返回模型实例
三:直接执行自定义Sql
使用extra:
1:Book.objects.filter(publisher__name='广东人员出版社').extra(where=['price>50'])
Book.objects.filter(publisher__name='广东人员出版社',price__gt=50)
2:Book.objects.extra(select={'count':'select count(*) from hello_Book'})
使用raw:
Book.objects.raw('select * from hello_Book')
自定义sql:
Book.objects.raw("insert into hello_author(name) values('测试')")
rawQuerySet为惰性查询,只有在使用时生会真正执行
执行自定义sql:
from django.db import connection
cursor=connection.cursor()
#插入操作
cursor.execute("insert into hello_author(name) values('郭敬明')")
#更新操作
cursor.execute('update hello_author set name='abc' where name='bcd'')
#删除操作
cursor.execute('delete from hello_author where name='abc'')
#查询操作
cursor.execute('select * from hello_author')
raw=cursor.fetchone() #返回结果行游标直读向前,读取一条
cursor.fetchall() #读取所有
45、如何利用orm进行子查询操作?
46、请总结orm的优缺点;
```
优点:
实现了代码与数据操作的解耦合
不需自己写原生sql, 提高开发效率
防止SQL注入, 通过对象操作的方式,默认就是防止sql注入的。
缺点:
牺牲性能, 对象到原生SQL势必会有转换消耗,对性能有一定的影响
复杂语句力不从心, 一些复杂的sql语句,用orm对象操作的方式很难实现,就还得用原生sql
```
47、字段中接收的参数都有什么意义 (e.g max_length)?
```
null #If True, Django will store empty values as NULL in the database. Default is False.
blank #If True, the field is allowed to be blank. Default is False.
db_column #The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.
db_index #If True, a database index will be created for this field.
default #The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.
editable # django admin中用,后面讲
help_text # django admin中用,后面讲
primary_key # If True, this field is the primary key for the model.
unique #If True, this field must be unique throughout the table
unique_for_date #Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field. For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn’t allow the entry of two records with the same title and pub_date.
unique_for_month #Like unique_for_date, but requires the field to be unique with respect to the month.
unique_for_year
verbose_name #A human-readable name for the field. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name
```
### 二、编程题
1、请使用socket模块实现一个简单的web服务器,用户在浏览器地址栏输入`http://127.0.0.1:8000`后,返回“OK”给浏览器;
```
conn.send(b"HTTP/1.1 200 OK\r\n\r\n")
conn.send(b"OK")
```
2、请写一个基于class的视图,返回字符串“Hello World”给客户端;
class DefineClassview(View):
"""演示类视图的定义和使用"""
def get(self, request):
"""处理GET请求业务逻辑"""
return HttpResponse('Hello World')
def post(self, request):
"""处理POST请求业务逻辑"""
return HttpResponse('Hello World')
def put(self, request):
return HttpResponse('Hello World')
3、请写一个视图函数,该函数判断客户端请求类型,如果是POST请求,打印"post",如果是GET请求,则打印"get";
def index(request):
if request.method == 'POST':
return HttpResponse("post")
elif request.method == 'GET':
return HttpResponse("get")
######下面的题必须要将操作同步到数据库
4、请写一个module名为Account,分别有username, email, password, register_date, signature字段;
```
from django.db import models
class Account(models.Model):
"""账户信息表"""
username = models.CharField(max_length=64, unique=True)
# EmailField的本质也是CharField,Django在此基础上做了格式验证,数据库中没有对应的email字段类型
email = models.EmailField()
password = models.CharField(max_length=128)
register_date = models.DateTimeField("注册日期", auto_now_add=True)
signature = models.CharField(verbose_name="签名", max_length=128, blank=True, null=True)
```
5、请写一个module名为Article,分别有title, content, account, pub_date, read_count字段;
```
class Article(models.Model):
"""文章表"""
title = models.CharField(max_length=255, unique=True)
content = models.TextField("文章内容")
account = models.ForeignKey("Account", verbose_name="作者", on_delete=models.CASCADE)
tags = models.ManyToManyField("Tag", blank=True)
pub_date = models.DateTimeField()
read_count = models.IntegerField(default=0)
```
6、请写一个module名为Tag,分别有name, date字段;
```
class Tag(models.Model):
"""文章标签表"""
name = models.CharField(max_length=64, unique=True)
date = models.DateTimeField(auto_now_add=True)
```
7、请配置django并连接到MySQL数据库,同步以上models到数据库中;
8、请使用orm分别插入数据到Account、Article、Tag表中;
9、请使用orm查询每一个account发表的文章数,按倒序排列;
10、请使用orm查询每一篇文章的title, content, username, email;
### django进阶
# 第十三章主要内容
```
1、Django session&cookie
2、CSRF验证
3、XSS
4、中间件
5、分页
6、自定义tags
7、Django Admin
8、Cache
9、Signals
10、Message
11、自定义用户认证
```

浙公网安备 33010602011771号