【转载】青魔法圣堂法术Django项目知识点汇总

本文转载自:博客园@ 申不二

博客地址:https://www.cnblogs.com/shenbuer/p/7683343.html

感谢分享。

目录

一、wsgi接口

二、中间件

三、URL路由系统

四、Template模板

五、Views视图

六、Model&ORM

七、Admin相关

八、Http协议

九、COOKIE 与 SESSION

十、Django的用户认证

十一、From与ModelForm

十二、分页

十三、缓存

十四、信号

十五、序列化

十六、Ajax

十七、数据库性能相关

0、Django的生命周期

 

一、wsgi接口

了解了HTTP协议和HTML文档,我们其实就明白了一个Web应用的本质就是:

  1. 浏览器发送一个HTTP请求;

  2. 服务器收到请求,生成一个HTML文档;

  3. 服务器把HTML文档作为HTTP响应的Body发送给浏览器;

  4. 浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。

所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。

如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。

正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。

这个接口就是WSGI:Web Server Gateway Interface。

WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求。我们来看一个最简单的Web版本的“Hello, web!”:

1
2
3
def application(environ, start_response):
    start_response('200 OK', [('Content-Type''text/html')])
    return '<h1>Hello, web!</h1>'

  

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

  • environ:一个包含所有HTTP请求信息的dict对象;

  • start_response:一个发送HTTP响应的函数。

application()函数中,调用:

1
start_response('200 OK', [('Content-Type''text/html')])

就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每个Header用一个包含两个strtuple表示。

通常情况下,都应该把Content-Type头发送给浏览器。其他很多常用的HTTP Header也应该发送。

然后,函数的返回值'<h1>Hello, web!</h1>'将作为HTTP响应的Body发送给浏览器。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,通过start_response()发送Header,最后返回Body。

整个application()函数本身没有涉及到任何解析HTTP的部分,也就是说,底层代码不需要我们自己编写,我们只负责在更高层次上考虑如何响应请求就可以了。

不过,等等,这个application()函数怎么调用?如果我们自己调用,两个参数environstart_response我们没法提供,返回的str也没法发给浏览器。

所以application()函数必须由WSGI服务器来调用。有很多符合WSGI规范的服务器,我们可以挑选一个来用。但是现在,我们只想尽快测试一下我们编写的application()函数真的可以把HTML输出到浏览器,所以,要赶紧找一个最简单的WSGI服务器,把我们的Web应用程序跑起来。

好消息是Python内置了一个WSGI服务器,这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。

运行WSGI服务

我们先编写hello.py,实现Web应用程序的WSGI处理函数:

1
2
3
4
5
# hello.py
 
def application(environ, start_response):
    start_response('200 OK', [('Content-Type''text/html')])
    return '<h1>Hello, web!</h1>'

然后,再编写一个server.py,负责启动WSGI服务器,加载application()函数:

1
2
3
4
5
6
7
8
9
10
11
# server.py
# 从wsgiref模块导入:
from wsgiref.simple_server import make_server
# 导入我们自己编写的application函数:
from hello import application
 
# 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
httpd = make_server('', 8000, application)
print ("Serving HTTP on port 8000..."
# 开始监听HTTP请求:
httpd.serve_forever()

确保以上两个文件在同一个目录下,然后在命令行输入python server.py来启动WSGI服务器:

 

注意:如果8000端口已被其他程序占用,启动将失败,请修改成其他端口。

启动成功后,打开浏览器,输入http://localhost:8000/,就可以看到结果了:

 注意

 

回到顶部

二、中间件

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件

中间件中一共有五个方法:

复制代码
process_request

- 有,直接执行当前中间件和上方中间件的process_response

- 应用: 用户登录授权(排除不需要登录的url)

process_view

 

process_exception

- process_tempalte_response
- 必须有返回值
- 必须对象中要有render方法

process_response

    - 必须有返回值
复制代码

 

中间件之process_request,process_response

process_request(self,request)

process_response(self, request, response)

当用户发起请求的时候会依次经过所有的的中间件,这个时候的请求时process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者

在django中叫中间件,在其他web框架中,有的叫管道,httphandle

 

中间件之process_view执行过程:

当最后一个中间的process_request到达路由关系映射之后,返回到中间件1的process_view,然后依次往下,到达views函数,最后通过process_response依次返回到达用户

中间件之process_exception

process_exception(self, request, exception)

当views的函数中出现错误时,就会执行process_exception方法

如果在中间中添加了process_exception方法,工作图示为:

  这样当用户发起请求的时候到达中间件3的process_request之后会到达urls路由关系映射这里,如果匹配到了就会到中间件1的process_view,然后依次传递到中间件3的process_view,到达view函数。如果view函数中有报错,则会从中间件3依次向上判断每个中间件的process_exception是否能匹配到这个错误信息,如果匹配到则直接返回到最后一个中间件,这里即中间件3的process_response,然后依次返回到用户,如果没有匹配到这个错误则直接在页面显示错误信息。如果view函数中没有错误,则到中间3即最后一个中间件3的process_response,然后依次向上,传到用户

中间件之process_template_responseprocess

process_template_response(self,request,response)

只有当views函数中返回的对象中具有render方法,是就会直接process_template_responseprocess

 中间件的应用

所有请求统一做处理时使用
- 登录验证

-添加访问日志等

 

自定义中间件

上述图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin

所以需要导入:from django.utils.deprecation import MiddlewareMixin

我们在项目文件下创建一个Middle目录,并在下面创建m1.py代码例子如下

 自定义中间件

配置settings.py

 自定义中间件-配置setting.py

 

返回顶部 

 三、URL路由系统(URLconf)

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

 URLconf说明

3.1 简单配置

 url配置实例
 url配置注意事项

3.2 有名分组(named group)

  上面的示例使用简单的、没有命名的正则表达式组(通过圆括号)来捕获URL 中的值并以位置 参数传递给视图。在更高级的用法中,可以使用命名的正则表达式组来捕获URL 中的值并以关键字 参数传递给视图。

  在Python 正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name 是组的名称,pattern 是要匹配的模式。

下面是以上URLconf 使用命名组的重写:

 url有名分组

这个实现与前面的示例完全相同,只有一个细微的差别:捕获的值作为关键字参数而不是位置参数传递给视图函数。例如:

 url有名分组实例

在实际应用中,这意味你的URLconf 会更加明晰且不容易产生参数顺序问题的错误 —— 你可以在你的视图函数定义中重新安排参数的顺序。当然,这些好处是以简洁为代价;有些开发人员认为命名组语法丑陋而繁琐。

3.3 URLconf 在什么上查找

URLconf 在请求的URL 上查找,将它当做一个普通的Python 字符串。不包括GET和POST参数以及域名。

例如,http://www.example.com/myapp/ 请求中,URLconf 将查找myapp/

在http://www.example.com/myapp/?page=3 请求中,URLconf 仍将查找myapp/

URLconf 不检查请求的方法。换句话讲,所有的请求方法 —— 同一个URL的POSTGETHEAD等等 —— 都将路由到相同的函数。

3.4 捕获的参数永远是字符串

每个捕获的参数都作为一个普通的Python 字符串传递给视图,无论正则表达式使用的是什么匹配方式。例如,下面这行URLconf 中:

url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

views.year_archive() 的year 参数将是一个字符串

3.5 指定视图参数的默认值

有一个方便的小技巧是指定视图参数的默认值。 下面是一个URLconf 和视图的示例

 View Code

 

  在上面的例子中,两个URL模式指向同一个视图views.page —— 但是第一个模式不会从URL 中捕获任何值。如果第一个模式匹配,page() 函数将使用num参数的默认值"1"。如果第二个模式匹配,page() 将使用正则表达式捕获的num 值。

3.1.6 路由分发( Including other URLconfs)

在项目中,若需要将某一应用下url统一跳转,则可以使用 Including other URLconfs

 路由分发(include other是url)

 返回顶部

四、Template模板

  python的模板:HTML代码+逻辑控制代码

4.1 模板支持的语法

4.1.1  变量(使用双大括号来引用变量)

语法格式:       {{var_name}}

Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。

 Django模板使用比较

4.1.2 深度变量的查找(万能的句点号)

在到目前为止的例子中,我们通过 context 传递的简单参数值主要是字符串,然而,模板系统能够非常简洁地处理更加复杂的数据结构,例如list、dictionary和自定义的对象。在 Django 模板中遍历复杂数据结构的关键是句点字符 (.)。

 句点号查找实例

4.1.3 变量的过滤器(filter)的使用

 filter过滤器使用说明

4.1.4自定义filter和simple_tag

a、在app中创建templatetags模块(必须的)

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

 自定义过滤器

c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

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

 调用自定义过滤器

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

注意:

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

 View Code

4.2 标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

语法格式:    {% tags %}

{% if %} 的使用 

{% if %}标签计算一个变量值,如果是“true”,即它存在、不为空并且不是false的boolean值,系统则会显示{% if %}和{% endif %}间的所有内容

 {% if%}标签使用

{% for %}的使用

{% for %}标签允许你按顺序遍历一个序列中的各个元素,每次循环模板系统都会渲染{% for %}和{% endfor %}之间的所有内容

 {% for %}标签使用

csrf_token标签

用于生成csrf_token的标签,用于防治跨站攻击验证。 其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

{% url %}

引用路由配置的地址

 {% url %}标签使用

{% with %}

用更简单的变量名替代复杂的变量名

 {% with %}标签使用

4.3 extend模板继承

步骤:

a、新建 base.html,放在template目录下

b、使用模板标签: {% block %}分块,用于子模板继承 

 新建母版文件(base.html)

c、子模版集成(即重载block块)

 子母版继承

继承的常见三层法:

 继承的常见三层法

模板继承的一些诀窍

 模板继承的诀窍

 返回顶部

 五、Views视图

django中请求处理方式有2种:FBV 和 CBV

 5.1 CBV(class base views)

CBV(class base views) 就是在视图里使用类处理请求。

5.1.1. 基本使用

使用方法为:urls.py 修改为如下:

 CBV中urls.py文件

views.py 修改为如下:

 CBV中views.py文件

5.1.2. 基于dispatch和继承实现用户登录代码

  1、写一个登录验证类

 CBV实现用户登录验证

2、修改views.py并继承验证

 CBV实现用户登录验证

5.1.3. 装饰器

1、get,post方法上,给任意函数添加

 get,post方法上

2、dispatch方法上,同时给get、post添加装饰器

 dispatch方法上

3、类上

 类上

4、特殊:CSRF Token只能加到dispatch

 CSRF Token只能加到dispatch

5.2 FBV(function base views)

FBV(function base views) 就是在视图里使用函数处理请求。

5.2.1. 基本使用

1、使用方法为:urls.py 修改为如下:

 FBV中urls.py文件

2、views.py 修改为如下:

 FBV中views.py文件

3、index.html

 index.html

5.2.2快捷函数

render函数

 render函数

 redirect函数

 redirect函数

返回顶部

六、Model&ORM

6.1、创建表

1、基本结构

 基本结构
 字段
 参数
 元信息
 拓展知识

2、连表结构

  • 一对多:models.ForeignKey(其他表)
  • 多对多:models.ManyToManyField(其他表)
  • 一对一:models.OneToOneField(其他表)
 应用场景:
 字段以及参数

6.2、操作表

1、基本操作

 基本操作

2、查询相关API

 查询相关API

3、进阶操作(了不起的双下划线)

利用双下划线将字段和对应的操作连接起来

 进阶操作

4、连表操作(了不起的双下划线)

利用双下划线和 _set 将表之间的操作连接起来

 表结构实例
 一对一操作
 一对多
 多对多操作

5、聚合查询和分组查询

<1> aggregate(*args,**kwargs):

   通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

 aggregate查询

<2> annotate(*args,**kwargs):

   可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。

 分组:annotate()查询

6、F查询和Q查询

 F查询和Q查询

 返回顶部

 

七、Admin相关

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

  • 创建后台管理员
  • 配置url
  • 注册和配置django admin后台管理页面

1、创建后台管理员

1
python manage.py createsuperuser

2、配置后台管理url

1
url(r'^admin/', include(admin.site.urls))

3、注册和配置django admin 后台管理页面

  a、在admin中执行如下配置

 配置admin,添加Model表

b、设置数据表名称

 设置数据表名称

c、一些常用的设置技巧(在admin.py文件中配置

 一些常用的设置技巧

d、打开表之后,设定默认显示,需要在model中作如下配置(在admin.py文件中配置

 设定默认显示

e、为数据表添加搜索功能(在admin.py文件中配置

 为数据表添加搜索功能

f、添加快速过滤(在admin.py文件中配置

 添加快速过滤

返回顶部

八、Http协议

8.1 HTTP概述

HTTPhypertext transport protocol),即超文本传输协议。这个协议详细规定了浏览器和万维网服务器之间互相通信的规则。

HTTP就是一个通信规则,通信规则规定了客户端发送给服务器的内容格式,也规定了服务器发送给客户端的内容格式。其实我们要学习的就是这个两个格式!客户端发送给服务器的格式叫请求协议;服务器发送给客户端的格式叫响应协议

特点:

  • HTTP叫超文本传输协议,基于请求/响应模式的!
  • HTTP是无状态协议。

URL:统一资源定位符,就是一个网址:协议名://域名:端口/路径,例如:http://www.oldboy.cn:80/index.html

8.2 请求协议

请求协议的格式如下:

 请求协议格式

浏览器发送给服务器的内容就这个格式的,如果不是这个格式服务器将无法解读!在HTTP协议中,请求有很多请求方法,其中最为常用的就是GETPOST

8.2.1 GET请求

HTTP默认的请求方法就是GET

1
2
3
* 没有请求体
* 数据必须在1K之内!
* GET请求数据会暴露在浏览器的地址栏中

GET请求常用的操作:

 GET请求常用的操作:

8.2.2 POST请求

 POST请求特点
 注意

8.3 接收自定义http头部(headers)

用Python的httplib库来做模拟客户端,参考网上写出模拟代码如下:

 模拟客户端client.py

其中'/headinfo/'为服务器的响应目录。

然后是服务端的响应代码,一个能够返回客户端自定义头部的模块

 server.py

结果:

结果

注意点:自定义请求头时,Django自动在头部META字典中的key值都会被加上“HTTP_”的前缀,category会变成 HTTP_CATEGORY ,auth-api 会变成 HTTP_AUTH_API

8.4 http请求request详解

 HttpRequest实例的属性

 8.5 HttpRequest 的方法

 HttpRequest 的方法

返回顶部

九、COOKIE 与 SESSION

9.1简介

 简介

9.2认证机制

 认证的机制

9.3认证应用

第一步: 先在templates目录下创建两个html,login.html负责登录页面。backend页面代表后台页面

 login.html
 
 backend.html

 第二步:编辑app01应用下的views.py文件,编写代码逻辑部分

 views.py

第三步,编辑mydjango目录下的urls.py文件。设置函数与页面的绑定关系

 urls.py

最后打开浏览器直接访问/backend/页面的时候直接就被重定向到了/login/

 总结

 总结

9.4cookie知识点:

 Cookie知识点

9.5session知识点:

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

1、数据库Session(默认)

 View Code

2、缓存Session

 View Code

3、文件Session

 View Code

4、缓存+数据库Session

 View Code

5、加密cookie Session

 View Code

扩展:Session用户验证

 View Code

 返回顶部

十、Django的用户认证

10.1认证登录

1
from django.contrib import auth

django.contrib.auth中提供了许多方法,这里主要介绍其中的三个:

10.1.1  authenticate()   

 authenticate

10.1.2  login(HttpRequest, user)  

 login

10.1.3  logout(request) 注销用户  

 logout

 

10.1.4 user对象的 is_authenticated()

要求:

1
2
3
1  用户登陆后才能访问某些页面,
2  如果用户没有登录就访问该页面的话直接跳到登录页面
3  用户在跳转的登陆界面中完成登陆后,自动访问跳转到之前访问的地址

方法1:

1
2
3
def my_view(request):
  if not request.user.is_authenticated():
    return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

方法2:login_required函数

django已经为我们设计好了一个用于此种情况的装饰器:login_requierd()

1
2
3
4
5
from django.contrib.auth.decorators import login_required
     
@login_required
def my_view(request):
  ...

若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings文件中通过LOGIN_URL进行修改)。并传递  当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。 

+++++++++++++++++++

10.2 User对象

User 对象属性:username, password(必填项)password用哈希算法保存到数据库

is_staff : 用户是否拥有网站的管理权限.

is_active : 是否允许用户登录, 设置为``False``,可以不用删除用户来禁止 用户登录

10.3 User 对象方法  

10.3.1  is_authenticated()

如果是真正的 User 对象,返回值恒为 True 。 用于检查用户是否已经通过了认证。
通过认证并不意味着用户拥有任何权限,甚至也不检查该用户是否处于激活状态,这只是表明用户成功的通过了认证。 这个方法很重要, 在后台用request.user.is_authenticated()判断用户是否已经登录,如果true则可以向前台展示request.user.name

10.3.2  创建用户

 使用 create_user 辅助函数创建用户

10.3.3  set_password(passwd)

 更改密码

10.3.4  check_password(passwd)

1
用户需要修改密码的时候 首先要让他输入原来的密码 ,如果给定的字符串通过了密码检查,返回 True

10.3.5 修改密码

 使用 set_password() 来修改密码

示例:注册

 View Code

示例:改密码

 View Code

 返回顶部

 

十一、Form与ModelForm

11.1 From

  Django会将表单的提交变得更加简单和安全,包括重构数据后在页面间传递,创建前端的HTML页面以及接收和处理客户端传来的数据。实施上,你只需要事先定义好form表单的各种属性,在前端页面简单调用即可。当然,Django为Form提供了许多属性,方便自定义,甚至你可以重写其中的一些方法。

应用:使用注册表完成验证并注册

1、urls.py

 urls.py

2、models.py

 models.py

3、在app 目录下新建 form.py

 form.py

4、views.py

 views.py

5、register.html

 register.html

11.2 ModelForm

 11.2.1ModelForm参数和使用

 ModelForm参数和使用

 

11.2.2 通过ModelForm完成三张表格的数据新增:

1)  在app01目录下建立forms.py文件,今后将所有的form都写在这个文件中,这个文件需要在views.py中导入,方便导入相应的FORM

2)  创建ModelForm:

forms.py:

 forms.py

 建立url与view的关联关系

1
url(r'^add/', echo.views.add), 

在views.py中建立相应的函数

views.py:

 views.py

在templates文件夹下建立HTML文件,add.html

add.html:

 add.html

返回顶部

十二、分页

12.1分页器的使用

 分页器参数及使用

12.2实现一个分页效果

index.html

 index.html

views.py

 views.py

返回顶部

十三、缓存

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

 Django6种缓存方式

1、配置

a、开发调试

 View Code

b、内存

 View Code

c、文件

 View Code

d、数据库

 View Code

e、Memcache缓存(python-memcached模块)

 View Code

f、Memcache缓存(pylibmc模块)

 View Code

2、应用

a. 全站使用

 View Code

b. 单独视图缓存

 View Code

c、局部视图使用

 View Code

返回顶部

十四、信号

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者。

1、Django内置信号

 Django内置信号说明

 

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

 注册信号
 信号应用举例

2、自定义信号

a. 定义信号

 定义信号

b. 注册信号

 注册信号

c. 触发信号

 触发信号

由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

 

返回顶部

十五、序列化

序列化

在django中,在将数据库中检索的数据返回给客户端用户,数据类型为QuerySet格式,而QuerySet格式不能被json格式化处理传到前端,因此在处理此类数据时有两种方法:

方法一:使用django自带的系列化模块 serializers模块

1、serializers

 使用serializers序列化

1、serializers序列化后的数据格式为列表,列表为每一个查询记录

  2、serializers模块不能跨表查询,涉及一对多查询时,只能查询到关联字段

方法二:查询时转换为QuerySet字典或列表格式

2、json.dumps

 json.dumps序列化

特殊的:

 datetime日期序列化

返回顶部

十六、Ajax

AJAX的优缺点

优点:

  • AJAX使用Javascript技术向服务器发送异步请求;
  • AJAX无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的局部,所以AJAX性能高;

缺点:

  • AJAX并不适合所有场景,很多时候还是要使用同步交互;
  • AJAX虽然提高了用户体验,但无形中向服务器发送的请求次数增多了,导致服务器压力增大;
  • 因为AJAX是在浏览器中使用Javascript技术完成的,所以还需要处理浏览器兼容性问题;

 js实现局部刷新

 js实现局部刷新

jquery实现的ajax

 jquery实现的ajax
 views.py

$.ajax参数

 $.ajax参数

响应参数

 响应参数

示例:

 示例

csrf跨站请求伪造

方法一

 csrf跨站请求伪造

方法二:

 csrf跨站请求伪造方法二

跨域AJAX

由于浏览器存在同源策略机制,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。

特别的:由于同源策略是浏览器的限制,所以请求的发送和响应是可以进行,只不过浏览器不接受罢了。

浏览器同源策略并不是对所有的请求均制约:

  • 制约: XmlHttpRequest
  • 不叼: img、iframe、script等具有src属性的标签

跨域,跨域名访问,如:http://www.c1.com 域名向 http://www.c2.com域名发送请求。

1、JSONP实现跨域请求

JSONP(JSONP - JSON with Padding是JSON的一种“使用模式”),利用script标签的src属性(浏览器允许script标签跨域)

 基于JSONP实现跨域Ajax - Demo

2、CORS

随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。

 

 简单请求与非简单请求
 * 关于“预检”

基于cors实现AJAX请求:

a、支持跨域,简单请求

服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

 HTML
 Torando

b、支持跨域,复杂请求

由于复杂请求时,首先会发送“预检”请求,如果“预检”成功,则发送真实数据。

    • “预检”请求时,允许请求方式则需服务器设置响应头:Access-Control-Request-Method
    • “预检”请求时,允许请求头则需服务器设置响应头:Access-Control-Request-Headers
    • “预检”缓存时间,服务器设置响应头:Access-Control-Max-Age
 HTML
 Tornado

c、跨域获取响应头

默认获取到的所有响应头只有基本信息,如果想要获取自定义的响应头,则需要再服务器端设置Access-Control-Expose-Headers。

 HTML
 Tornado

d、跨域传输cookie

在跨域请求中,默认情况下,HTTP Authentication信息,Cookie头以及用户的SSL证书无论在预检请求中或是在实际请求都是不会被发送。

如果想要发送:

    • 浏览器端:XMLHttpRequest的withCredentials为true
    • 服务器端:Access-Control-Allow-Credentials为true
    • 注意:服务器端响应的 Access-Control-Allow-Origin 不能是通配符 *
 HTML
 Tornado
 

 返回顶部

 十七、数据库性能相关

select_related 与 prefetch_related 区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
user_list = models.UserInfo.objects.all()
    for row in user_list:
        # 只去取当前表数据
 
select_related,主动连表查询【FK】
     
    user_list = models.UserInfo.objects.all().select_related('FK字段')
    for row in user_list:
        # 只去取当前表数据和FK表关联字段
 
 
    user_list = models.UserInfo.objects.values(...)
    for row in user_list:
        # 只去取当前表数据和FK表关联字段
 
    ==》 连表降低性能
 
prefetch_related 被动连表
    user_list = models.UserInfo.objects.all().prefetch_related('FK字段')
 
    # [obj,obj,obj]
    # 查询用户表models.UserInfo.objects.all() 1000
    # 把用户表中所有的ut_id拿到, 用户类型ID [1,2,3]
    # 把用户表中所有的ut_id拿到, 用户类型ID [21,21,31]
    # select * from UsetType where id in [1,2,3]
    # select * from xx where id in [21,21,31]
    user_list = models.UserInfo.objects.all().prefetch_related('ut','xx')
    for row in user_list:
        print(row.name, row.pwd, row.ut.caption)
补充:
    # [obj,obj,obj]
    # user_list = models.UserInfo.objects.all().only('name')   # 只取某个字段 select name from userinfo
    # user_list = models.UserInfo.objects.all().defer('name')  # 排除当前字段
    # for row in user_list:
    #     print(row.pwd)

select_related,主动连表查询【FK】,当连表不多时用select_related查询

prefetch_related 被动连表,当连表较多时,用prefetch_related查询

 返回顶部

未添加:

自定义分页、验证码、头像预览、富文本编辑框

 

posted on 2018-11-27 16:08  墨书韶光(魏泯i)  阅读(151)  评论(0编辑  收藏  举报

导航

by: 魏泯