导图社区 python网站开发(Django框架语法大全)
此导图是本人学习网站开发时做的超详细笔记,里面有相关语法的用法截图,学习的是django框架,希望对你有帮助!
编辑于2022-05-21 17:51:21Django框架
介绍
Django发音为[`dʒæŋɡəʊ],是用python写的开源web开发框架,并遵循MVC设计,是劳伦斯出版集团为了开发以新闻内容为主的网站而开发出来的。由于Django在近年来的迅速发展,应用越来越广泛,被著名IT开发杂志SDTimes评选为2013SDTimes100,位列"API、库和框架"分类第6位,被认为是该领域的佼佼者。
Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用,多个组件可以很方便的以"插件"形式服务于整个框架,Django有许多功能强大的第三方插件,甚至可以很方便的开发出自己的工具包,这使得Django具有很强的可扩展性。它还强调快速开发和DRY(DoNotRepeatYourself)原则。
特点
对比Flask框架,Django原生提供了众多的功能组件:
提供项目工程管理的自动化脚本工具
数据库ORM支持(Object Relational Mapping对象关系映射)
模板
表单
Admin管理站点
文件管理
认证权限
session机制
缓存
MVT模式
释义
Model-View-Template(模型-视图-模板),Django (python) 的框架。
核心思想
其核心思想是分工、解耦,强制性的使应用程序的输入、处理和输出分开,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。
模块分工
M全拼为Model,与MVC中的M功能相同,负责和数据库交互,进行数据处理。
V全拼为View,与MVC中的C功能相同,接收请求,进行业务处理,返回应答。
T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html。
演示
对比
MVC模式
释义
Model-View-Controller(模型-视图-控制器),其他语言的设计框架。
核心思想
其核心思想是分工、解耦,强制性的使应用程序的输入、处理和输出分开,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。
模块分工
Model,主要封装对数据库层的访问,对数据库中的数据进行增、删、改、查操作。
View,用于封装结果,生成页面展示的html内容。
Controller,用于接收请求,处理业务逻辑,与Model和View交互,返回结果。
演示
相关文档
官网
https://www.djangoproject.com/
https://docs.djangoproject.com/en/4.0/topics/
1.11版双语文档
https://yiyibooks.cn/xx/Django_1.11.6/index.html
Django Book 教程
https://djangobook.com/
Tange With Django 教程
https://www.tangowithdjango.com/book17/
global_settings.py
settings.py顶部的参考文档
初始操作流程
进入指定虚拟环境
创建Django项目
创建子应用
使用PyCharm打开项目
设置PyCharm虚拟环境
安装/注册子应用
(修改数据库引擎)
(运行开发服务器)
定义模型类
模型迁移
生成迁移文件
执行迁移
定义视图
在子应用的views.py里定义视图函数。
定义URL
在子应用里新建urls.py文件
修改工程下的urls.py文件
操作数据库
模板
新建模板文件夹
创建模板(.html文件)
设置模板路径
视图将数据传给模板
模板处理数据
安装Django框架
安装/更新
sudo pip install django==版本号
安装位置
工具包都会安装到/usr/local/lib/python2.7/dist-packages路径下
多项目的问题
如果在一台电脑上, 想开发多个不同的项目, 需要用到同一个包的不同版本, 如果使用上面的命令, 在同一个目录下安装或者更新, 新版本会覆盖以前的版本, 其它的项目就无法运行了。解决方法是使用虚拟环境。
搭建虚拟环境
作用
虚拟环境可以搭建独立的python运行环境,使得单个项目的运行环境与其它项目互不影响。
优点
避免版本冲突
让使用了python不同版本的两个项目不会互相冲突。
便于环境迁移
虚拟环境仅仅存安装了与项目相关包,迁移的时候,不会存在其他的软件包。
位置
所有的虚拟环境都位于/home/下的隐藏目录.virtualenvs下。
搭建步骤
安装虚拟环境
sudo pip install virtualenv
sudo pip install virtualenvwrapper
创建存放虚拟环境的目录
mkdir ~/.virtualenvs
“~”表示在用户主目录下创建该目录,“.”表示隐藏目录。
修改 ~/.bashrc 文件
打开文件
vi ~/.bashrc
在末行添加:
export WORKON_HOME=$HOME/.virtualenvs source /usr/local/bin/virtualenvwrapper.sh
运行 ~/.bashrc 文件
source ~/.bashrc
创建虚拟环境
在python2中创建
mkvirtualenv 虚拟环境名称
在python3中创建
mkvirtualenv -p python3.6 虚拟环境名字
这样可以指定在3.6中创建虚拟环境。
mkvirtualenv -p python3 虚拟环境名字
备注
创建虚拟环境需要联网。
创建成功后, 会自动工作在这个虚拟环境上,提示符最前面会出现虚拟环境名。
使用方法
查看所有虚拟环境
workon
进入指定虚拟环境
workon 虚拟环境名
退出虚拟环境
deactivate
删除虚拟环境
rmvirtualenv 虚拟环境名
注意
不能删除正在使用的虚拟环境,要先退出或切换至其他虚拟环境。
虚拟环境中安装工具包
注意
在虚拟环境中的命令前如果加上sudo,则表示在真实环境中操作。
工具包安装的位置
python2版本
~/.virtualenvs/py_flask/lib/python2.7/site-packages/
python3版本
~/.virtualenvs/py3_flask/lib/python3.5/site-packages/
安装工具包
pip install 包名
查看安装的包
pip list
设置PyCharm使用虚拟环境
方法一
打开项目时设置虚拟环境
方法二
打开项目后设置虚拟环境
可以通过which python来获取当前虚拟环境的python脚本路径。
创建Django项目
代码
django-admin startproject 项目工程名
需要在虚拟环境中操作。
django-admin中间不是下划线。
说明
settings.py
项目的整体配置文件。
urls.py
项目的URL配置文件。
wsgi.py
项目与WSGI兼容的Web服务器入口。
manage.py
项目管理文件,通过它管理项目。
告知PyCharm这是Django项目
子应用
创建子应用
释义
子应用就是项目里的各个模块。
代码
python manage.py startapp 子应用名
manage.py是上面创建项目工程时自动生成的管理文件。
需要先cd切换到项目工程目录再执行此代码。
子应用名尽量用小写。
说明
admin.py文件
跟网站的后台管理站点配置相关。
apps.py文件
用于配置当前子应用的相关信息。
migrations目录
用于存放数据库迁移历史文件。
models.py文件
用户保存数据库模型类。
tests.py文件
用于开发测试用例,编写单元测试。
views.py文件
用于编写Web应用视图。
演示
注册子应用
说明
创建出来的子应用目录文件虽然被放到了工程项目目录中,但是子应用和当前工程没有联系,django工程并不能立即直接使用该子应用,需要注册安装后才能使用。
注册
将子应用的配置信息文件apps.py中的Config类添加到工程项目的配置文件settings.py中的INSTALLED_APPS列表中。
INSTALLED_APPS = ['子应用名']
建议使用“子应用名.apps.类名”,这样也可以使用类里的其他参数。
或
INSTALLED_APPS = ['子应用名.apps.类名Config']
子应用配置
参数
AppConfig.name
表示这个配置类是加载到哪个应用的,每个配置类必须包含此属性,默认自动生成。
AppConfig.verbose_name
用于设置该应用的直观可读的名字,此名字在Django提供的Admin管理站点中会显示。
演示
如果增加了“verbose_name”属性后,网页上没反应,则可能是注册子应用时出的问题:
初始化子应用
python manage.py migrate 子应用名 zero
将生成的迁移文件撤回应用,同时删除DB中migrations表中的迁移信息
运行开发服务器
说明
在开发阶段,为了能够快速预览到开发的效果,django提供了一个纯python编写的轻量级web服务器,仅在开发阶段使用。
方法一
python manage.py runserver IP地址:端口
不写IP和端口则默认IP是127.0.0.1:8000。
方法二
演示
备注
如果出现这个报错,要删除widgets.py文件里152行的逗号:
django默认工作在Debug调式模式下,如果增加、修改、删除文件,服务器会自动重启。
停止服务器
ctrl+C
管理员设置
创建管理员
python manage.py createsuperuser
重置密码
python manager.py changepassword 用户名
配置文件 settings.py
BASE_DIR 项目根目录
释义
当前工程的根目录,Django会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。
代码
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
表示当前文件绝对路径下的上两级目录。
说明
__file__:当前文件的文件名。
os.path.abspath():文件的绝对路径。
os.path.dirname():文件所在的目录。
演示
DEBUG
释义
DEBUG = True
调试模式下,支持静态文件,修改代码后程序自动重启,且程序异常时,向前端显示详细的错误追踪信息。
DEBUG = False
非调试模式下,程序异常时仅返回Server Error (500)。
部署线上运行的Django不要运行在调式模式下,要修改为DEBUG=False和ALLOW_HOSTS。
语言与时区
LANGUAGE_CODE = 'zh-Hans' TIME_ZONE = 'Asia/Shanghai'
演示
ALLOWED_HOSTS
释义
允许以哪个主机来访问后端(默认是127.0.0.1)。
设置
如果想以真实IP(或域名)来访问,需要加到列表里。
开发阶段建议建议设置为“ALLOWED_HOSTS = ['*']”,因为真实IP会变动。
备注
如果列表里只填了真实IP,则只能用真实IP来运行服务器和访问; 如果列表里填了真实IP和127.0.0.1并用“runserver 真实IP”来运行服务器,也只能用真实IP来访问; 如果列表里填了真实IP和127.0.0.1并用“runserver 127.0.0.1”或点击【Run】来运行服务器,则只能用127.0.0.1来访问; 如果列表里填了真实IP和127.0.0.1并用“runserver 0.0.0.0”来作为IP运行服务器,则能用真实IP和127.0.0.1来访问。
URLconf 路由配置
作用
网站获取地址栏中的URL信息,然后与编写好的URLconf逐条匹配。如果匹配成功则调用对应的视图来处理请求,如果所有的URLconf都没有匹配成功,则返回404错误。
设置
settings.py
ROOT_URLCONF = '项目名.urls'
项目/urls.py
url(正则表达式, include('子应用.urls', namespace='命名空间'))
子应用/urls.py(新建)
from 子应用.views import 函数名
url(正则表达式, views.py的函数名, name='路由的别名')
备注
“^”和“$”分别表示以……开头和以……结尾。
“r”表示字符串不转义,这样在正则表达式中只需写一个“/”。
不能在开头处加“/”,推荐在结尾处加,如“index/”,不加"/"也是正确的。
是否结尾带“/”以所属公司风格为准。
URL匹配过程
在浏览器中输入的路径会和urlpatterns列表中的每一项匹配。(浏览器中输入的“http://ip:port/”和get参数、post参数不参与正则匹配。如“http://127.0.0.1:8000/index/?a=10”去掉域名和参数部分后,只剩下“index/”参与正则匹配。)如果匹配成功,则直接引导到相应的模块 (继续在子应用中匹配,匹配成功则返回相应的视图,匹配失败则继续和后边的工程url的每一项进行匹配);如果匹配失败,则返回404页面。
反向解析得到路由
作用
可以通过url的name别名来反回对应的路径。
导入模块
from django.urls import reverse
或
from django.core.urlresolvers import reverse
reverse:v. 颠倒、反向
代码
reverse(viewname='路由的name别名')
或
reverse(viewname='命名空间:路由的name别名')
演示
子应用/url.py
urlpatterns = [ url(r'^index/', index, name='首页'), ]
子应用/views.py
def index(request): ........
其他子应用/views.py
path = reverse(viewname='首页') return redirect(path)
跳转到子应用。
优点
例如,实际开发过程中,可能会有多个页面都会需要跳转到首页,如果根据产品需要,让浏览器原本输入“index”改为输入“home”才能访问首页,则我们需要将其他多个子应用views.py的“return redirect('/index/')”改为“return redirect('/home/')”。而加上“path = reverse(viewname='首页')”和将“return redirect('/index/')”改为“return redirect(path)”,则只需要把首页的views.py的“url(r'^index/', index, name='首页')”改为“url(r'^home/', index, name='首页')”就能满足产品需求。
路由名命名空间
作用
为了防止多个子应用中的name路由别名出现相同而相互冲突,在项目/urls.py里可以给每个子应用加上命名空间 (类似人类社会里的一班的张三和二班的张三)。
操作
在 项目/urls.py 的“include()”里添加“namespace”,如此一来,路由的别名“name”就变为了“namespace:name”。
演示
项目/urls.py
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include('子应用1.urls', namespace='子应用1')), url(r'^', include('子应用2.urls', namespace='子应用2')), ]
子应用/urls.py
urlpatterns = [ url(r'^index/', index, name='首页'), ]
子应用/views.py
def index(request): ........
其他子应用/views.py
path = reverse(viewname='子应用1:首页') return redirect(path)
跳转到子应用。
备注
“namespace”习惯上使用子应用的名字。
PostMan工具
释义
PostMan 是一款功能强大的网页调试与发送网页 HTTP 请求的 Chrome 插件,可以直接去对我们写出来的路由和视图函数进行调试,是后端程序员必须知道的工具。
下载安装
安装方式1
去 Chrome 商店直接搜索 PostMan 扩展程序进行安装。
安装方式2
https://www.getpostman.com/官网下载桌面版。
安装方式3
将已下载好的 PostMan 插件文件夹从电脑拖入到浏览器的【扩展程序】。
使用
打开
初次使用
静态文件 static
释义
项目中的CSS、图片、js都是静态文件。一般会将静态文件放到一个单独的目录中。在html页面中调用时,需要指定静态文件的路径。静态文件可以放在项目根目录下,也可以放在子应用目录下 (由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理)。
操作
在项目根目录下创建static目录
在settings.py中修改静态文件的两个参数
STATIC_URL = '/static/'
注意
当访问的路径是“http://ip:port + STATIC_URL + 文件名”时,Django会认为这是静态资源,便会到静态资源文件夹中匹配资源。
STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), ]
静态资源文件夹
模型 models.py
说明
Model中内嵌了ORM框架
Object Relational Mapping,它是MVC框架中重要的一部分。它的作用是在关系型数据库和对象之间作一个映射,这样就不需要再去和复杂的SQL语句打交道,只要像操作对象一样操作数据库即可。
属性的定义
class 模型类名(models.Model)
属性名 = models.字段类型(字段选项)
属性名不要使用“python”“mysql”,不要含有连续的多个下划线。
字段类型后面不能有逗号。
字段类型 :
AutoField
自动增长的IntegerField,通常不用指定,不指定则Django会自动创建属性名为id的自动增长属性
BooleanField
布尔字段,值为True或False
NullBooleanField
支持Null、True、False三种值
CharField
字符串,参数max_length表示最大字符个数
TextField
大文本字段,一般超过4000个字符时使用
IntegerField
整数
DecimalField
十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数
FloatField
浮点数
DateField
日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add、auto_now、default是相互排斥的,组合将会发生错误
TimeField
时间,参数同DateField
DateTimeField
日期时间,参数同DateField
FileField
上传文件字段
ImageField
继承于FileField,可对上传的内容进行校验,确保是有效的图片
ForeignKey(数据表名, on_delete)
外键。选项on_delete设置当删除主表数据时,从表数据如何处理 :
on_delete=models.CASCADE
级联,删除主表数据时连同删除外键表中数据,此为默认项。
on_delete=models.PROTECT
保护,通过抛出 ProtectedError 异常,来阻止删除主表中被外键引用的数据。
on_delete=models.SET_NULL
删除主表数据时设置为NULL,仅在该字段null=True允许为null时可用。
on_delete=models.SET_DEFAULT
删除主表数据时设置为默认值,仅在该字段设置了默认值时可用。
on_delete=models.SET()
设置为特定值或者调用特定方法。
on_delete=models.DO_NOTHING
不做任何操作,如果数据库前置指明级联性,此选项会抛出 IntegrityError 异常。
外键在数据表中的字段名会自动加"_id":
字段选项 :
max_length=最大长度
CharFiled 字段必须设置该选项
null=Ture
是否允许为空,默认是False
blank=Ture
是否允许为空白,默认是False
区别
null是数据库范畴的概念,blank是表单验证范畴的。 null是数据库级别的null,默认为false,如果设置为null=True,则字段值可以为:null或空字符串 null=false时,若不给字段赋值,django会默认赋值空字符串('') blank表示在表单验证的时候允许为空,其他没有区别
db_column=字段名称
字段的名称,如果未指定,则使用属性的名称
db_index=Ture
是否在表中会为此字段创建索引,默认值是False
default=默认值
模型类设置的默认值,是定义模型实例化对象时给对象的默认属性,和数据表的缺省值不一样。定义了默认值的模型类,生成数据表时,相关的字段不会有缺省值。
primary_key=Ture
若为True,则该字段会成为模型的主键字段,一般作为AutoField字段类型的选项使用,默认值是False
django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
unique=Ture
这个字段在表中是否必须有唯一值,默认值是False
verbose_name=显示信息
在后台显示的信息 (作为第一个参数时,无需写“verbose_name=”)
choices=有序字典
枚举类型
定义模型类枚举类型的选项
有序字典名=((键1, 值1), (键2, 值2))
查询模型类枚举类型的选项
模型类.有序字典[键]
演示
模型迁移
生成迁移文件
作用
创建数据表和模型的对应关系。
多个子应用
python manage.py makemigrations
单个子应用
python manage.py makemigrations 子应用名
说明
新建表或修改表结构后需要生成迁移文件。
执行迁移
作用
根据数据库迁移文件生成对应SQL语句并执行 → 在数据库中生成数据表。
多个子应用
python manage.py migrate
单个子应用
python manage.py migrate 子应用名
说明
如果在数据库中已有子应用需要的数据表(数据库的表结构需要和models.py的模型类的表结构一致),则只需要生成迁移文件,无需再执行迁移。
操作数据库
查看数据库
备注
默认采用sqlite3数据库来存储数据
安装驱动
查看
进入数据库后台
方法一
方法二
http://127.0.0.1:8000/admin
注册模块类
作用
注册模型成功后, 就可以在站点管理界面方便快速的管理数据。
代码
from 子应用名.models import 模型类名1, 模型类名2
admin.site.register(模型类名)
在子应用的admin.py里操作。
演示
增加数据
发布内容到数据库
方法一
方法二
优化模型类的展示
修改数据库引擎
修改settings.py
sqlite是嵌入式的小型的关系型数据库,主要在移动端使用。
(虚拟环境中安装相应数据库)
修改工程下的__init__.py
每当改变数据库引擎时都要修改这文件。
创建数据库
生成迁移文件
可能的报错
执行迁移(在数据库中创建数据表)
备注
数据库更换为MySQL后,在PyCharm左侧目录处不会有数据库文件。
修改表结构注意事项
修改字段大小
只需在模型类中和数据库中修改字段的大小。
数据表结构的改动较大
如果表的改动很大(甚至删除了表), 在修改完models.py后,到数据库中删除要改动的表,删除0001_initial.py文件,删除数据表django_migrations中相关的迁移记录。 然后执行ython manage.py makemigrations和python manage.py migrate即可。
models.py里追加数据表
如果在models.py里有数据表并已经执行迁移的情况下追加新的数据表(即新的模型类),只需再执行“python manage.py makemigrations”和“python manage.py migrate”
数据库修复
如果数据库里有些表被误删,需要先删除项目目录下的数据库,再重新运行项目。
修改数据表名称
方法一
方法二
db_table = '表名'
如果用此方法,还需要删除migrations目录下的initial.py,以及重新生成迁移文件和执行迁移。
修改后台显示的表名
verbose_name = '显示的表名'
verbose_name_plural = '显示的表名'
展示表中数据
使用已存在的数据表
1.连接本地数据库
2.查看生成的模型类
python manage.py inspectdb
3.输出重定向将其保存为文件
python manage.py inspectdb 数据库中你想用的表格的名字 > 路径\新模型类文件名.py
路径是manage.py文件的相对路径。
4.使用这个models.py文件覆盖app中的models文件。【overwrite】
5.新生成的是一个不可修改/删除的models,修改 class Meta中的 managed = True 则告诉django可以对数据库进行操作。
6.安装核心 Django 表
python manage.py migrate
安装所有额外需要的数据库记录,像是后台权限和内容类型。
shell工具
说明
Django的manage工具提供了shell命令,帮助我们启动当前工程的运行环境(如连接好数据库等),以便直接在终端中执行测试python语句。(shell 所有的命令后面都是写到 views.py 里的)
进入
python manage.py shell
python manage.py shell -i ipython
-i ipython表示使用ipython,这样写代码有提示。
退出
exit()
quit()
或
quit
CTRL+D
操作模型类
导入模型类
from 子应用名.models import 模块类名
增加 (修改)
方式一
模型类名.objects.create( 属性1 = 值1, 属性2 = 值2 )
objects 是模型的管理类。
外键字段名要写成“外键名_id”。
外键在数据表中的字段名会自动加"_id":
方式二
对象名 = 模型类名( 属性1 = 值1, 属性2 = 值2 ) 对象名.save()
删除
方式一
对象名 = 模型类名.objects.get(属性名=值) 对象名.delete()
方式二
模型类名.objects.filter(属性名=值).delete()
filter:n./v.过滤
修改
方式一
模型类名.objects.filter(属性名=值).update( 属性1 = 值1, 属性2 = 值2 )
返回值是受影响的行数。
方式二
对象名 = 模型类名.objects.get(属性名=值) 对象名.属性名 = 值 对象名.save()
查询
基本查询
多个结果
模型类名.objects.all()
查询数量
模型类名.objects.count()
BookInfo.objects.count()
或
BookInfo.objects.all().count()
或
Address.objects.filter(user_id=request.user.id).count()
过滤查询
模型类名.objects.过滤器(过滤条件)
过滤器:
过滤出单一结果
get()
get(过滤条件) 的过滤条件有0个或多个满足时,抛出异常。
过滤出多个结果(列表)
filter()
排除掉符合条件的结果
exclude()
exclude:vt.把……排除在外
过滤条件:
属性名__条件表达式=值
相等
属性名__exact=值
exact:adj.精确的
BookInfo.objects.filter(id__exact=1)
可简写为:
BookInfo.objects.filter(id=1)
或
BookInfo.objects.get(id=1)
属性名__iexact=值
不区分大小写。
模糊查询 (包含)
属性名__contains=值
BookInfo.objects.filter(name__contains='传')
备注
如果要包含%无需转义,直接写即可。
实际上是SQL的“LIKE”。
属性名__icontains=值
不区分大小写。
指定值开头
属性名__startswith=值
属性名__istartswith=值
不区分大小写。
指定值结尾
属性名__endswith=值
BookInfo.objects.filter(name__endswith='概论')
属性名__iendswith=值
不区分大小写。
空查询
属性名__isnull=True
BookInfo.objects.filter(name__isnull=True)
范围查询
属性名__in=[值1, 值2, 值3]
BookInfo.objects.filter(id__in=[1,3,5])
比较查询
大于
属性名__gt=值
BookInfo.objects.filter(id__gt=3)
(greater then)
大于等于
属性名__gte=值
(greater then equal)
小于
属性名__lt=值
BookInfo.objects.filter(pub_date__lt='1990-1-1')
查询1990年1月1日前发表的图书。
(less then)
小于等于
属性名__lte=值
(less then equal)
日期时间查询
属性名__year=值
BookInfo.objects.filter(pub_date__year=1980)
属性名__month=值
属性名__day=值
属性名__week_day=值
属性名__hour=值
属性名__minute=值
属性名__second=值
属性间比较
from django.db.models import F
模型类名.objects.过滤器(属性1...=F('属性2'))
BookInfo.objects.filter(readcount__gt=F('commentcount'))
查询阅读量大于等于评论量的图书。
BookInfo.objects.filter(readcount__gt=F('commentcount')*2)
查询阅读量大于2倍评论量的图书。
逻辑查询
与
方法一
模型类名.objects.过滤器(过滤条件1, 过滤条件2)
BookInfo.objects.filter(readcount__gt=20,id__lt=3)
查询阅读量大于20,并且编号小于3的图书。
方法二
模型类名.objects.过滤器1(过滤条件1).过滤器2(过滤条件2)
BookInfo.objects.filter(readcount__gt=20).filter(id__lt=3)
查询阅读量大于20,并且编号小于3的图书。
即筛选两次。
方法三
from django.db.models import Q
模型类名.objects.过滤器(Q(过滤条件1)&Q(过滤条件2))
或
from django.db.models import Q
模型类名.objects.过滤器(Q(过滤条件1) | Q(过滤条件2))
BookInfo.objects.filter(Q(read_count__gte=50) | Q(id__gte=3))
非
from django.db.models import Q
模型类名.objects.过滤器(~Q(过滤条件))
BookInfo.objects.filter(~Q(id=3))
或
BookInfo.objects.exclude(id=3)
备注
Q对象 部分了解即可。
聚合函数
Avg平均
from django.db.models import Avg
Count计数
from django.db.models import Count
模型类名.objects.count('属性名')
使用count时一般不使用aggregate()过滤器,count函数的返回值是一个数字。
导入时大写Count,书写时小写count。
Max最大
from django.db.models import Max
Min最小
from django.db.models import Min
Sum求和
from django.db.models import Sum
模型类名.objects.aggregate(Sum('属性名'))
备注
aggregate 的返回值是一个字典类型:{'属性名__聚合类': 值}
聚合函数 部分了解即可。
排序
升序
模型类名.objects.all().order_by('属性名')
all() 也可以替换成 filter(过滤条件)。
降序
模型类名.objects.all().order_by('-属性名')
如果是无条件查询所有即all(),并且排序,则可不写all()。
关联查询
一查多
查询一方中对应的多方的信息。
一方的模型类对象 = 一方的模型类.objects.get(过滤条件) 一方的模型类对象.多方的模型类(小写)_set.过滤器(过滤条件)
查询id=1的书籍里的所有人物。
备注
一方中并没有多方的属性,故不能直接调用。
get 改为 filter,则得到的是对象列表,不是对象,会报错。
多查一
查询多方中对应的一方的信息。
多方的模型类对象 = 多方的模型类.objects.get(过滤条件) 多方的模型类对象.多方模型类中的外键名
查询id=1的人物对应的书籍。
备注
多方中原本就有一方的属性(即外键属性),故可直接调用。
查对象
模型类.objects.get(外键名=外键对象)
实际执行:
模型类.objects.get(外键名_id=外键对象.id)
关联过滤查询
多方作为筛选条件
过滤条件 :
多方模型类名__多方属性名__条件运算符=值
一方作为筛选条件
过滤条件 :
一方模型类名__一方属性名__条件运算符=值
查询集 QuerySet
释义
查询结果集,表示从数据库中获取的对象集合(不是简单的列表)。
使用all()、filter()、exclude()、order_by()都会返回查询集。
对查询集可以再次调用过滤器进行过滤:模型类名.objects.过滤器1(过滤条件1).过滤器2(过滤条件2)
查询集.exists()
判断查询集中是否有数据,如果有则返回True,没有则返回False。
特性
惰性执行
创建查询集时不会访问数据库,直到调用数据时,才会访问数据库(调用数据的情况包括迭代、序列化、与if合用)。
优点是在views.py里可以准备很多个查询集,不执行查询的话,不会影响数据库的性能。
缓存
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用内存的数据,减少了数据库的查询次数。
备注
如果是两个查询集,则无法重用缓存,每次查询都会与数据库进行一次交互。
这两句代码,每句都有“BookInfo.objects.all()”,也就是每次都生成了新的查询集,所以无法重用查询集。
限制查询集
下标
查询集[索引]
切片
查询集[下标1: 下标2]
对查询集进行切片后返回一个新的查询集,不会立即执行查询。
第一个下标是0的话可以省略。
注意
不支持负数索引。
分页
导入分页类
from django.core.paginator import Paginator
语法
对象名 = Paginator(查询集, 每页显示数)
对象名.page(页码)
对象名.num_pages
返回总页码数
演示
参考文档
https://docs.djangoproject.com/en/1.11/topics/pagination/
视图 views.py
说明
对于MVT框架,用户在URL中请求的是视图,视图接收请求后进行处理,并将处理的结果返回给请求者。
视图是一个定义在子应用views.py里的一个函数。
函数的第一个参数是uWSGI(即服务器)传过来的请求信息request,它是HttpRequest的实例对象。
返回的响应是HttpRespond的实例对象/子类实例对象,也可重定向redirect。
演示
HttpRequest对象
请求的4种途径
URL路径参数
释义
即通过URL的特定部分来向服务器传递参数,如/weather/beijing/2018,可以在服务器端的路由中用正则表达式截取。
说明
如果想从URL中获取值,需要在正则表达式中使用分组“()”。
通过URL路径获取参数有两种途径,分别是位置参数和关键字参数。两种方式不能混合使用,在一个正则表达式中只能使用一种参数方式。
位置参数
子应用/urls.py
urlpatterns = [ url(r'^(参数1)/(参数2)/$', 函数名), ]
改进后:
views.py
def 函数名(request, 参数1, 参数2): ......
关键字参数 (推荐)
子应用/urls.py
urlpatterns = [ url(r'^(?P<参数别名1>参数1)/(?P<参数别名2>参数2)/$', 函数名), ]
(括问大P尖参)
views.py
def 函数名(request, 参数别名1, 参数别名2): ......
查询字符串
释义
即通过查询字符串(Query String)来向服务器传递参数。
说明
HttpRequest对象的GET属性、POST属性都是QueryDict类型的对象。
备注
与python字典不同,QueryDict类型的对象可以用来处理一个键带有多个值的情况。
查询字符串不区分请求方式,即假使客户端进行POST方式的请求,依然可以通过request.GET获取请求中的查询字符串数据。
代码
浏览器
网址?key1=value1&key2=value2
views.py
获取QueryDict对象
QueryDict对象名 = request.GET
获取请求路径中的查询字符串参数。
获取单个属性值
QueryDict对象名['属性名']
QueryDict对象名.get('属性名', '默认值')
如果键不存在则返回None,也可设置默认值。
备注
如果一个键同时拥有多个值,则获取最后一个值。
获取多个属性值
QueryDict对象名.getlist('属性名', '默认值')
如果键不存在则返回空列表[],也可设置默认值。
演示
请求体参数
释义
即通过请求体来向服务器发送数据,比如表单数据、json数据、xml。
说明
请求体的数据格式不固定,可以是表单类型字符串,可以是JSON字符串,可以是XML字符串,应区别对待。可以发送请求体数据的请求方式有POST、PUT、PATCH、DELETE方式。
Django默认开启了CSRF防护,会对上述请求方式进行CSRF防护验证,在测试时可以关闭CSRF防护机制,方法为在settings.py文件中注释掉CSRF中间件。
表单类型 Form Data
说明
前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。
备注
GET方式提交数据是在地址栏以查询参数的形式提交数据的,不安全。 POST方式提交的数据在请求体里。
操作
PostMan
【POST】-【Body】-【form-data】
views.py
QueryDict对象 = request.POST
演示
非表单类型 Non-Form Data
说明
非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。(现在只学JSON,XML到爬虫部分再学)
操作
PostMan
【POST】-【Body】-【raw】-【∨】
JSON数据必须使用双引号,且最后一个键值对后面不能加逗号。
views.py
bytes类型对象 = request.body
JSON类型字符串 = bytes类型对象.decode()
字典与JSON转换
导入模块
import json
JSON字符串→字典
json.loads(JSON)
load:v.装上
字典→JSON字符串
json.dumps(字典)
dump:v.放下
演示
演示
文件类型数据
获取
request.FILES
请求头
释义
即通过请求头(header)来向服务器发送数据。
获取
request.META
常见请求头
演示
其他常用HttpRequest对象属性
HttpResponse对象
代码
return HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
content:返回的内容,尽量只传递二进制和字符串类型。
content_type:是MIME类型,语法形式是“大类/小类”。
如"application/json""text/html""text/css""text/javascript""image/png""image/gif""image/jpeg"
status:范围是100~599。
JsonResponse
作用
自动将数据转换为json,同时设置响应头 Content-Type 为 application/json。
原理
代码
from django.http import JsonResponse
return JsonResponse(字典)
演示
HttpResponse子类
Django提供了一系列HttpResponse的子类,可以快速设置状态码。
页面跳转 (重定向)
导入模块
from django.shortcuts import redirect
redirect:vt. 使改方向
代码
return redirect(网址或'/路径/')
return redirect('/index/')
演示
状态保持
释义
浏览器请求服务器是无状态的,即请求时服务器不知道当前用户之前做过什么。 (原因:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。)
实现状态保持主要有两种方式:将数据保存在客户端使用Cookie,将数据保存在服务端使用Session。
Cookie
说明
网站为辨别用户身份、进行session(会话)跟踪而储存在用户本地终端的数据(常经过加密,建议不要存储密码等敏感信息,因为电脑上的浏览器可能被他人使用)。浏览器会将Cookie的key、value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等。服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。
特点
Cookie以键值对的格式进行信息的存储。
Cookie基于域名安全,不同域名的Cookie是不能互相访问的。如使用浏览器访问京东时在浏览器中写了Cookie信息,使用同一浏览器访问百度时,百度无法访问到京东写的Cookie信息。
当浏览器请求某网站时,会将浏览器存储的跟该网站相关的所有Cookie信息提交给网站服务器。
流程
浏览器第一次请求时没有cookie信息,服务器便给浏览器设置cookie信息到响应头的 set_cookie 中,浏览器接收到响应后,会保存响应头中的cookie信息。浏览器往后的请求都会在请求头中携带cookie信息,服务器便会接收到浏览器的cookie信息,用于辨别用户身份。
代码
子应用/urls.py
(略)
views.py
设置cookie
响应对象 = HttpResponse()
响应对象.set_cookie(cookie信息名, value=cookie值, max_age=cookie有效期)
有效期单位是秒,默认是“None”(表示临时cookie,浏览器关闭就删除)。
return 响应对象
演示
获取cookie
cookie信息名 = request.COOKIES.get('cookie名')
request.COOKIES 得到的是字典。
return HttpResponse()
演示
删除cookie
响应对象 = HttpResponse()
响应对象.delete_cookie('cookie信息名')
原理
或
响应对象.set_cookie(cookie名, value=cookie值, max_age=0)
演示
Session
启用Session
Django项目默认启用Session,如需禁用session,将下图中的session中间件注释掉即可。
特点
session需要依赖于cookie,如果浏览器禁用了cookie,则session不能实现。
流程
以登录的过程为例:用户第一次登录的时候,服务器验证用户名和密码后,将用户的信息(用户名、密码等)保存在session里,同时在响应头中自动生成一个cookie信息 (包含sessionid),浏览器再保存这个cookie信息。浏览器往后的请求都会在请求头中携带cookie里的sessionid信息,服务器验证sessionid正确后,会根据sessionid从内存中读取用户的session信息。
代码
子应用/urls.py
(略)
views.py
设置session
request.session['键名'] = 值
获取session
request.session
存储方式设置
数据库存储
设置方法
安装Session应用
INSTALLED_APPS = ['django.contrib.sessions',]
数据库引擎
SESSION_ENGINE='django.contrib.sessions.backends.db'
这是默认存储方式,可以不写此代码。
储存session信息的数据表
由表结构可知,操作Session包括三个数据:键、值、过期时间。
session在redis中是str类型:vhifibidsbnhk7r(随机数,即sessionid): '{name: python}',其中随机数是sessionid。
本地缓存
说明
存储在本机内存中,比数据库的方式读写更快,但如果丢失则不能找回。
设置方法
数据库引擎
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存储
说明
优先从本机内存中存取,如果没有则从数据库中存取。
设置方法
数据库引擎
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
Redis存储
说明
在redis中保存session,需要引入第三方扩展,我们可以使用django-redis来解决。
设置方法
虚拟环境中安装扩展
pip install django-redis
settings.py
配置方法一
1.设置redis作为django的缓存设置
2.数据库引擎
SESSION_ENGINE = 'redis_sessions.session'
配置方法二
1.设置redis作为django的缓存设置
文档解释:
caches:缓存
"127.0.0.1:6379/1":选择使用redis的1号库(redis默认是0号库)。
2.数据库引擎
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
3.指定本地的session使用的本地缓存名称是'default'
SESSION_CACHE_ALIAS = 'default'
文档解释
中文文档:
https://django-redis-chs.readthedocs.io/zh_CN/latest/
注意
可能的报错
如果redis的ip地址不是本地回环127.0.0.1,而是其他地址,访问Django时,可能出现Redis连接错误,如下:
解决方法
打开redis的配置文件
sudo vim /etc/redis/redis.conf
添加特定ip地址
在配置项进行修改(比如要添加10.211.55.5地址)。
重新启动redis服务
sudo service redis-server restart
Session操作
以键值对的格式写session
request.session['键']=值
根据键读取值
request.session.get('键',默认值)
清除所有session,在存储中删除值部分
request.session.clear()
删除session包括key在内的整条数据
request.session.flush()
删除session中的指定键及值,在存储中只删除某个键及对应的值
del request.session['键']
设置session的有效期
request.session.set_expiry(value)
说明
如果value是一个整数,session将在value秒没有活动后过期。
如果value为0,那么用户session的Cookie将在用户的浏览器关闭时过期。
如果value为None,那么session有效期将采用系统默认值。
(系统默认有效期为两周 ,可以通过在settings.py中设置 SESSION_COOKIE_AGE 来设置全局默认值。)
查看session有效期
类视图
释义
类视图是以面向对象的方式定义的;而之前定义视图是以函数的方式定义的,称为函数视图。
说明
虽然函数视图便于理解,但是如果遇到一个视图对应的路径提供了多种不同HTTP请求方式的支持时,便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳。
优点
代码可读性好。
类视图相对于函数视图有更高的复用性, 如果其他地方需要用到某个类视图的某个特定逻辑,直接继承该类视图即可。
作用
在一个视图中处理get和post请求。
例如在登录页面既要有get请求展示登录页面,也要有post请求实现登录功能。
views.py
from django.views.generic import View
类视图需要继承自View。
或
from django.views.generic.base import View
class 类视图名(View): def http方法名(self, request): ...... def http方法名(self, request): ......
需要在类视图中定义http方法来实现不同的业务逻辑。
http方法的第二个参数是请求实例对象。
子应用/urls.py
from . import view
from . import * 代表导入这一级的模块。
url(r'正则表达式', 视图文件名.类视图名.as_view(), name='路由的别名')
第二个参数"views.类视图名.as_view()"是视图的函数名。
as_view()方法的返回值就是将类视图转成的函数视图。
演示
原理
view函数:初始化。 dispatch函数:判断当前http方法的小写是否正确,并实现业务逻辑。
类视图添加装饰器
class 类视图名(View): @method_decorator(装饰器) def ......
登录验证
应用场景
“用户中心”等界面必须登录之后才能访问,这就需要判断是否已经登录。
导入扩展类
from django.contrib.auth.mixins import LoginRequiredMixin
代码
class 类视图名(LoginRequiredMixin, View): ......
注意
LoginRequiredMixin 类要写在 View 类之前,因为这两个类都有dispatch()方法,想实现登陆的验证功能,需要继承 LoginRequiredMixin 的dispatch()方法。
原理
authenticated:v. 已认证;已验证
演示
中间件
释义
Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设计为开发者提供了一种无侵入式的开发方式,增强了Django框架的健壮性。
参考文档
https://docs.djangoproject.com/en/1.11/topics/http/middleware/
定义
说明
中间件的文件可以放在任意位置。
debug模式下,每个中间件的初始化会执行两次。
文档解释
注册
setting.py
MIDDLEWARE = [路径.中间件文件名]
应用演示
每次访问时,验证浏览器的cookie信息中是否携带用户名,没携带则认为未登录。
中间件顺序
请求前的执行顺序是注册顺序,请求后的执行顺序是逆注册顺序。
在请求视图被处理前,中间件由上至下依次执行; 在请求视图被处理后,中间件由下至上依次执行。
(自带)模板 templates文件夹
说明
将前端的内容定义在模板中,然后再把模板交给视图调用,视图将模板文件作为HttpResponse()的参数,响应给客户端,客户端便可以看到一个漂亮的网页。
创建模板
操作
新建一个和子应用同一级的文件夹templates,在里面创建子应用同名文件夹。在子应用同名文件夹下新建.html模板文件。
演示
设置模板路径
settings.py
'DIRS': [os.path.join(BASE_DIR, 'templates')]
在settings.py的TEMPLATES列表里的DIRS里设置模板路径。
演示
BASE_DIR就是当前工程的路径。
模板渲染
复杂方法
from django.http import HttpResponse from django.template import loader def index(request): # 1.获取模板 template=loader.get_template('xxx.html') context={'变量名': 数据} # 2.渲染模板 return HttpResponse(template.render(context))
简单方法
from django.shortcuts import render def index(request): context={'变量名': 数据} return render(request,'xxx.html',context)
在子应用的views.py的函数中,通过render()函数将指定的内容传给指定的模板,并将处理结果响应给客户端。
render:v.渲染
原理
render()函数最后也是return HttpResponses()。
应用
网页显示数据库数据
查询数据库数据
后面会详细讲。
模板循环显示
模板语言后面会详细讲。
在使用jinja2模板引擎后,django自带的模板语法“{{ 变量 }}”就不能用了。
效果
模板语法
变量
{{ 变量名 }}
使用模板语言“{{ 变量名 }}”来替换模板里的内容。
列表元素
{{ 列表名.下标 }}
字典元素
{{ 字典名.键名 }}
备注
“键名”无需加引号。
运算符
比较运算符
==
!=
<
>
<=
>=
布尔运算符
and
or
not
注意
运算符左右两边必须加上空格。
for 循环语句
{% for 变量名 in 列表名 %} 执行的循环语句 {{ forloop.counter }} {% empty %}列表为空或不存在时执行的语句 {% endfor %}
“{{ forloop.counter }}”表示当前是第几次循环。
“{% ... %}”代表开始流程控制,“{% end... %}”代表结束流程控制。
if 条件语句
{% if 条件语句1 %} 执行语句1 {% elif 条件语句2 %} 执行语句2 {% else %} 执行语句3 {% endif %}
注释
单行注释
{#...#}
可直接在空白行里按 ctrl+/ 。
多行注释
{% comment %} ... {% endcomment %}
说明
注释内容在浏览器的源码里是看不到的。
参考文档
https://docs.djangoproject.com/en/1.11/
过滤器
释义
过滤器本质上是个函数。
语法
变量|过滤器:参数
在变量、标签中使用管道符号“|”来使用过滤器,用于进行计算、转换操作。
如果过滤器需要参数,则使用冒号“:”传递参数。
过滤器举例
变量|safe
禁用转义,告诉模板这个变量是安全的,可以解释执行。
不使用 safe 过滤器:
变量|default:默认值
默认值,如果变量不存在时则返回默认值。
变量|length
长度,返回字符串包含字符的个数,或列表、元组、字典的元素个数。
变量|date
日期,用于对日期类型的值进行字符串格式化。
Y表示年,格式为4位,y表示两位的年。
m表示月,格式为01,02,12等。
d表示日, 格式为01,02等。
j表示日,格式为1,2等。
H表示时,24进制,h表示12进制的时。
i表示分,为0-59。
s表示秒,为0-59。
模板继承
作用
众多模板之间会有相同的部分,模板继承可以减少代码重用。
父模板
{% block 名称 %} ...... {% endblock 名称 %}
作用
标签block用于在父模板中预留区域,留给子模板填充差异性的内容。
备注
endblock 后面的名称可以省略,但建议写上。
演示
子模板
{% extends '路径/父模板名.html' %}
备注
此代码要写在子模板文件的第一行,表示子模板继承父模板,默认继承父模板的所有内容。
{% block 名称 %} ...... {% endblock 名称 %}
备注
子模版不必重写父模版中的所有预留区域,如果没有重写,则使用父模版定义的默认值,如果重写了但省略填充内容,则代表子模版不要这块预留区域。
演示
jinja2模板
介绍
Jinja2是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,尤其是Flask框架内置的模板语言。jinja2比Django自带的模板性能好很多,功能更多,可读性比较好,而且语法更加灵活。
安装
pip install jinja2
使用jinja2引擎
TEMPLATES = [ {'BACKEND': 'django.template.backends.jinja2.Jinja2'}]
loop
说明
Django的forloop在jinja2里是loop。
jinja2自定义过滤器
文档描述
步骤
自定义过滤器 (新建文件)
这个文件可以创建在项目的任意位置。
如此一来,在jinja2模板里使用的date就指向了djangp里的date,jinja2就可以使用date函数了。
指定jinja2的环境
演示
备注
pycharm默认的模板引擎是django自带的模板引擎,所以它认为这段代码有错。可以告知pycharm现在的引擎是jinja2。
与Django模板的区别
jinja2模板不能有多行注释。
Django的forloop在jinja2里是loop。
jinja2的过滤器与Django过滤器不一样。
其他
缺点
不利于页面静态化。
直接获取变量
jinja2模板引擎中自带request变量(与django默认模板引擎一样),可以直接获取使用“{{ request.user }}”等变量。
防止CSRF攻击
释义
CSRF全拼为Cross Site Request Forgery,译为跨站请求伪造。 CSRF指攻击者盗用了你的身份,以你的名义发送恶意请求,包括以你名义发送邮件,发消息,盗取账号,转账......
攻击示意图
代码举例
正规网站
钓鱼网站
解决方法
方法一
给用户发送短信验证码,用户转账时用户需要输入短信验证码,系统对比验证码与系统发出的一致再转账。
方法二
用户每次刷新转账页面时都生成一个随机验证码,将这个随机码同时发给HTML(隐藏起来)和cookie信息中,转账时先验证两个验证码是否一致。
设置步骤
在后台给用户生成一个随机验证码(可使用Django自带的get_token函数来生成),并将随机码传递到html页面和用户的cookie信息中。
服务器的那份随机码若保存在服务器中,则每次转账都需要读取服务器的数据库,所以改为存放在cookie中。
黑客拿不到用户的cookie信息(因为同源策略),也拿不到html页面中隐藏的验证码。而且每次刷新转账页面都会生成新的随机码,所以黑客就算使用两个一样的码来代替也不行。
在转账的页面获取后端传过来的随机码,并将其隐藏,用户点击转账时,随机码会连同账号、金额一起发送给后台。
说明
解决方法的本质是在请求的参数中加入验证码。
Django默认开启了CSRF防护。
同源策略
源
源(origin)是协议、域名、端口号的总和。
同源
若地址里面的协议、域名和端口号均相同则属于同源。
举例
以下是相对于 http://www.a.com/test/index.html 的同源检测(http默认端口号80) • http://www.a.com/dir/page.html ----成功,只有路径不同 • http://www.child.a.com/test/index.html ----失败,域名不同 • https://www.a.com/test/index.html ----失败,协议不同 • http://www.a.com:8080/test/index.html ----失败,端口号不同
同源策略
同源策略是浏览器的一个安全机制,不同源的客户端,脚本在没有明确授权的情况下,不能读写对方资源。例如当一个浏览器的两个tab页中分别打开来自百度和谷歌的页面时,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
报错汇总