MVC介绍:
MVC的全拼为Model-View-Controller, 最早由TrygveReenskaug在1978年提出,是施乐帕罗奥多研究中心(Xerox PARC)在20世纪80年代为程序语言Smalltalk发明的一-种软件设计模式,是为了将传统的输入(input) 、处理( processing)、输出(output)任务运用到图形化用户交互模型中而设计的。随着标准输入输入设备的出现,开发人员只需要将精力集中在业务逻辑的分析与实现上。后来被推荐为Oracle旗下Sun公司Java EE平台的设计模式,并且受到越来越多的使用ColdFusion和PHP的开发者的欢迎。现在虽然不再使用原来的分工方式,但是这种分工的思想被沿用下来,广泛应用于软件工程中,是一种典型并且应用广泛的软件架构模式。MVC结构提供了一种按功能对各种对象进行分割的方法(这些对象是用来维护和表现数据的),其目的是为了将各对象间的耦合程度减至最小。现在的MVC结构中,模型(Model)代表应用程序的数据(data) 和用于控制访问和修改这些数据的业务规则(businessrule)。通常模型被用来作为对现实世界中一个处理过程的软件近似,当定义-一个模型时,可以采用--般的简单的建模技术。当模型发生改变时,它会通知视(View) ,并且为视提供查询模型相关状态的能力。同时,它也为控制器(Controller)提供访问封装在模型内部的应用程序功能的能力。-一个视(View)用来组织模型的内容。它从模型那里获得数据并指定这些数据如何表现。当模型变化时,视负责维持数据表现的一- 致性。视同时将用户要求告知控制器(Controller) 。控制器(Controller) 定义了应用程序的行为;它负责对来自视的用户要求进行解释,并把这些要求映射成相应的行为,这些行为由模型负责实现,在独立运行的GUI客户端,用户要求可能是一些鼠标单击或是菜单选择操作。在一个WEB应用程序中,他们的表现形式可能是一些来自客户端的GET或POST的HTTP请求,模型所实现的行为包括处理业务和修改模型的状态。根据用户要求和模型行为的结果,控制器选择一个视作为对用户请求的应答,通常一组相关功能集对应一个控制器。
MVC框架的核心思想是:解耦,让不同的代码块之间降低耦合,增强代码的可扩展性和可移植性,实现向后兼容。
M全拼是Model,主要是封装对数据库层的访问,内嵌ORM框架,实现面向对象的编程来操作数据库,不用考虑数据库的差异性,简单配置就可以完成数据库切换。ORM是将python中的对象转化为关系型数据库操作,将关系型数据库中的行转化为python当中的对象。ORM不用程序员自己手写SQL语句。
V全拼是View,用于封装结果,内嵌了模板引擎,实现动态展示数据。
C全拼是Controller,用于接收GET或POST请求,处理业务逻辑,与Model和View交互,返回结果。
转存失败重新上传取消
Django简介
Django,是用python语言写的开源web开发框架,并遵循MVC设计,并且有一个专有名词:MVT。T全拼为Template,与MVC中的V功能相同,负责封装构造要返回的html,内嵌了模板引擎。
MVT
转存失败重新上传取消
差异就在于图中的黑线部分:
转存失败重新上传取消
转存失败重新上传取消
创建虚拟环境:mkvirtualenv django_env -p python3
pip install django==1.11.11
mkvirtualenv #创建虚拟环境
rmvirtualenv #删除虚拟环境
workon # 进入虚拟环境=
deactivate # 退出虚拟环境
#pip
pip install #安装依赖包
pip uninstall #卸载依赖包
pip list # 查看已安装的依赖包
创建一个工程
生成一个django项目工程的使用方法:
django-admin startproject 工程名称
说明:在pycharm里的terminal里输入此命令
工程目录的说明
各文件的作用:
settings-py是项目的整体配置文件
uris.py是项目的URL配置文件
wsgi.py是项目与WSGI兼容的Web服务器入口
manage.py是项目管理文件。通过它管理项目
创建子应用
python manage.py startapp 子应用名
说明:进入工程主目录里创建
各文件作用:
__init__.py
admin.py文件跟网站的后台管理站点配置相关。
apps.py配置文件用于配置当前子应用的相关信息。
models.py 文件用户保存数据库模型类。
views.py视图文件用于编写web应用视图。
migrations目录用于存放数据库迁移历史文件。
项目目录中创建数据库:
运行生成迁移
迁移
总结:
进入桌面,防止权限问题cd Desktop
进入虚拟环境:workon py_django
创建项目文件:django-admin stratproject test1
进入项目目录:cd test1
创建应用:python manage.py startapp booktest
安装应用
虚拟环境:一个python项目运行所需要包含的集合。
数据操作:
进入项目的shell,进行简单的API操作
按ctrl+d或输入quit()可以退出shell
创建book=BookInfo()
book.*** = ***
book.save()
删除:book.delete()
查询:BookInfo.objects.all()
BookInfo.object.get()
关系:根据图书对象找英雄对象book.heroinfo_set.all()
根据英雄找图书:hero.book
后台管理
●使用Django的管理模块,需要按照如下步骤操作
。1.管理界面本地化
。2.创建管理员,
。3.注册模型类
。4.自定义管理页面
1.管理界面本地化
●本地化是将显示的语言、时间等使用本地的习惯,这里的本地化就是进行中国化,中国大陆地区使用简体中文,时区使用亚洲/上海时区,注意这里不使用北京时区表示
LANGUAGE_CODE = ‘zh-Hans’
TIME_ZONE = ‘Asia/Shanghai’
2、创建管理员
python manage.py createsuperuser
转存失败重新上传取消
python manage.py runserver
转存失败重新上传取消
。
Web 应用程序处理流程
学习目标:
了解 web 框架
web 应用程序处理流程
Web 应用程序处理流程
转存失败重新上传取消
Web 框架的意义
Web 应用程序的本质
框架程序学习内容
总结:
环境安装
学习目标:
创建虚拟环境
创建一个单独的虚拟环境, 搭建项目.
mkvirtualenv django_env -p python3
安装 Django
使用 django 1.11.11 版本,注意需要联网
pip install django==1.11.11
我们这里使用 django 1.11.11 这个版本, 现在最新的是 django 2.x 的版本, 但是因为是最新的, 企业使用的不是很多, 所以我们这里还是使用 1.x 版本.
虚拟环境相关命令 和 pip 相关命令
# 虚拟环境
mkvirtualenv # 创建虚拟环境
rmvirtualenv # 删除虚拟环境
workon # 进入虚拟环境、查看所有虚拟环境
deactivate # 退出虚拟环境
# pip
pip install # 安装依赖包
pip uninstall # 卸载依赖包
pip list # 查看已安装的依赖库
总结:
学习目标:
能够创建 Django 工程
能够了解 Django 工程中的目录结构
创建工程的命令为:
#
生成一个
django
项目工程的使用方式
:
django-admin startproject
工程名称
例如:
需求如下: 在桌面的 code 目录中, 创建一个名为 demo 的工程.
实现:
我们可以在桌面定义一个 code 目录, 在目录中,
创建一个名为 demo 的项目工程,可执行如下命令:
# 将目录切换到code中:
cd code
# 调用 django 项目生成命令,生成项目:
django-admin startproject demo
执行后,code 目录中会多出一个新目录, 名为 demo,此即为新创建的工程目录。
这个新创建出来的目录,其实是我们下载的一个 django 开发模板, 我们可以在这个模板中进行 django 的开发.
我们可以看到刚刚生成的项目目录结构为:
转存失败重新上传取消
转存失败重新上传取消
各个文件的作用:
学习目标:
能够使用对应的命令把当前项目运行起来
项目运行后, 能够利用浏览器查看
在开发阶段,为了能够快速预览到开发的效果
django 提供了一个纯 python 编写的轻量级 web 服务器,仅在开发阶段使用。
# 命令格式:
python manage.py runserver
例如:
我们可以通过命令行进入刚刚创建的项目目录中:
# 进入创建的 demo 工程目录
cd demo
运行服务器命令如下:
# 调用如下命令, 就可以使我们的项目运行起来
# 默认运行在 127.0.0.1:8000 的 IP 和 端口上:
python manage.py runserver
# 我们也可以在刚刚的命令后面增加 IP:PORT 参数, 指定特定的 IP 和 端口号运行:
python manage.py runserver IP
地址
:
端口
运行成功后命令行界面:
转存失败重新上传取消
这里会看到一些红色的提示信息, 这些不是错误, 是提示我们有一些没有使用的迁移, 这里不用管它.
查看运行效果:
在浏览器中输入网址“ 127.0.0.1:8000 ”便可看到效果。
转存失败重新上传取消
学习目标:
创建子应用. 以及配置子应用
我们可以在项目的根目录下, 调用命令行, 创建子应用:
#
创建子应用的常见命令
:
python manage.py startapp
子应用名称
例如:
在刚才创建的 demo 工程中,想要创建一个用户 users 子应用模块,可执行:
#
进入项目的根目录中
:
cd ~/Desktop/code/demo
#
执行生成子应用的指令
,
生成一个叫
users
的子应用
:
python manage.py startapp users
执行后,可以看到工程目录中多出了一个名为 users 的子目录。
一般一个子应用代表一个模块, 例如: 购物车模块, 支付模块, 商品展示模块等...
查看此时的工程目录,结构如下:
转存失败重新上传取消
转存失败重新上传取消
生成的子应用中各个文件的作用:
创建出来的子应用目录文件虽然被放到了工程项目目录中,但是 django 工程并不能立即直接使用该子应用,需要注册安装后才能使用。
settings 中默认的配置信息
settings 文件里, installed_apps 列表中工程默认配置的信息:
转存失败重新上传取消
添加子应用到 settings 中
配置子应用信息也被称为: 注册安装一个子应用,
即, 将子应用的配置信息文件 apps.py 中的 Config 类添加到 INSTALLED_APPS 列表中。
例如:
将刚创建的 users 子应用中 apps.py 文件的信息
( users.apps.UsersConfig ), 添加到 INSTALLED_APPS 中, 如图所示:
转存失败重新上传取消
使当前总的项目知道我们新添加的模块(子应用). 这样方便项目工程调用.
python manage.py startapp
子应用名称
settings.py
文件中进行配置,才可以使用,否则项目工程不知道添加的子应用模块.学习目标:
视图创建和运行
打开刚创建的 users 模块,在 views.py 中编写视图代码。
# 从 django.http 模块中导入 HttpRespose
fromdjango.http
importHttpResponse
def index(request):
"""
index视图
:param request: 包含了请求信息的请求对象
:return: 响应对象
"""
return
HttpResponse(
"hello the world!")
说明:
1) 在子应用中新建一个 urls.py 文件保存该应用的路由
转存失败重新上传取消
2) 在 users / urls.py 文件中定义路由信息
# 从 urls 模块中导入 url
fromdjango.conf.urls
importurl
# 从当前目录导入我们的视图模块 views
from.
importviews
# urlpatterns 是被 django 自动识别的路由列表变量
urlpatterns = [
# 每个路由信息都需要使用 url 函数来构造
# url (路径, 视图)
url(
r'^index/$', views.index),
]
3) 在工程总路由 demo / urls.py 中添加子应用的路由数据。
# 导入:
fromdjango.conf.urls
importurl, include
fromdjango.contrib
importadmin
urlpatterns = [
url(
r'^admin/', admin.site.urls),
# django默认就有的路由配置信息
# 额外添加如下的路由配置信息:
url(
r'^users/', include(
'users.urls')),
]
include 函数除了可以传递字符串之外,也可以直接传递应用的 urls 块,如
fromdjango.conf.urls
importurl, include
fromdjango.contrib
importadmin
import users.urls
# 先导入应用的urls模块
urlpatterns = [
url(
r'^admin/', admin.site.urls),
# url(r'^users/', include('users.urls')),
url(
r'^users/', include(users.urls)),
# 添加应用的路由
]
4) 启动运行
重新启动 django 程序
python manage.py runserver
在浏览器中输入网址127.0.0.1:8000/users/index/ 可看到返回的信息
转存失败重新上传取消
配置文件
学习目标:
了解配置文件 settings.py
能够认识配置文件中的 BASE_DIR, DEBUG, 语言等选项
BASE_DIR
指当前工程的根目录,Django 会依此来定位工程内的相关文件,我们也可以使用该参数来构造文件路径。
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEBUG
设置是否为调试模式,创建工程后初始值为 True ,即默认工作在调试模式下。
作用:
转存失败重新上传取消
转存失败重新上传取消
注意:部署线上运行的 Django 不要运行在调式模式下,记得修改 DEBUG=False
如果为非调试模式:
程序出错后, 浏览器仅显示 500 的错误代码, 不会显示具体的错误信息:
转存失败重新上传取消
本地语言与时区
初始化的工程默认语言和时区为英语和 UTC 标准时区
LANGUAGE_CODE = 'en-us' # 语言
TIME_ZONE = 'UTC' # 时区
可以将语言和时区修改为中国大陆信息:
LANGUAGE_CODE = 'zh-hans' # 中文
TIME_ZONE = 'Asia/Shanghai' # 亚洲上海时区
转存失败重新上传取消
总结:
学习目标:
了解什么是静态文件
知道如何配置静态文件加载路径
我们一般会把项目中前端写的 CSS、图片、js 以及 html 等看做静态文件 。
静态文件我们会放在一个静态文件夹中, 统一管理
我们在 html 页面中调用时,需要指定静态文件的路径,故, Django 中提供了一种用于配置静态文件路径的解析方式。
静态文件可以放在项目根目录下,也可以放在应用的目录下,由于有些静态文件在项目中是通用的,所以推荐放在项目的根目录下,方便管理。
为了提供静态文件访问路径,我们需要在项目的 settings.py
文件中配置两个参数:
例如:
1) 在项目根目录下创建 static_files 目录来保存静态文件。
如图:
转存失败重新上传取消
2) 在 demo / settings.py 中修改静态文件的两个参数为
# 这个参数默认存在
STATIC_URL =
'/static/'
# 我们可以添加这个参数, 用于补全静态文件路径
STATICFILES_DIRS = [
os.path.join(BASE_DIR,
'static_files'),
]
3)此时在 static_files 添加的任何静态文件都可以使用网址 /static/ 文件在 static_files 中的路径 来访问了。
例如
我们向 static_files 目录中添加一个 index.html 文件,在浏览器中就可以使用127.0.0.1:8000/static/index.html 来访问:
转存失败重新上传取消
或者我们在 static_files 目录中添加了一个子目录和文件 goods/detail.html,在浏览器中就可以使用127.0.0.1:8000/static/goods/detail.html 来访问。
注意:
Django 仅在调试模式下(DEBUG=True)能对外提供静态文件。
当DEBUG=False工作在生产模式时,Django不再对外提供静态文件,需要是用collectstatic命令来收集静态文件并交由其他静态文件服务器来提供。(详细在部署时会讲)
路由说明
学习目标:
路由的定义和使用
什么是路由?
url 的了解:
# 第一种写法:
http://www.itcast.cn:80/users/index/?a=1&b=2&c=3#box
# 第二种写法:
http://192.168.238.128:80/users/index/?a=1&b=2&c=3#box
其中:
http:// 代表使用的协议
www.itcast.cn 指的是访问的域名
80 指的是调用的端口
/users/index/ 指的是路由部分
?a=1&b=2&c=3 指的是查询字符串
#box 指的是锚点
转存失败重新上传取消
路由定义位置
Django 的主要路由信息定义在工程同名目录下的 urls.py 文件中,该文件是 Django 解析路由的入口。
每个子应用为了保持相对独立,可以在各个子应用中定义属于自己的 urls.py 来保存该应用的路由。然后用主路由文件包含各应用的子路由数据。
除了上述方式外,也可将工程的全部路由信息都定义在主路由文件中,子应用不再设置 urls.py。如:
from django.conf.urls import url
from django.contrib import admin
import users.views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^users/index/$', users.views.index)
]
路由解析顺序
Django 在接收到一个请求时,从主路由文件中的 urlpatterns 列表中以由上至下的顺序查找对应路由规则,如果发现规则为 include 包含,则再进入被包含的 urls 中的 urlpatterns 列表由上至下进行查询。
值得关注的由上至下的顺序,有可能会使上面的路由屏蔽掉下面的路由,带来非预期结果。例如:
urlpatterns = [
url(r'^say', views.say),
url(r'^sayhello', views.sayhello),
]
即使访问 sayhello/ 路径,预期应该进入 sayhello 视图执行,但实际优先查找到了 say 路由规则也与 sayhello/ 路径匹配,实际进入了 say 视图执行。
提示:需要注意定义路由的顺序,避免出现屏蔽效应。
两种解决方法:
第一种:
from django.conf.urls import url
from . import views
urlpatterns = [
# 1. 调整书写顺序
url(r'^sayhello', views.sayhello),
url(r'^say', views.say)
]
第二种:
2.调整正则书写方式:
from django.conf.urls import url
from . import views
urlpatterns = [
# 2.调整正则:
url(r'^say/$', views.say),
url(r'^sayhello/$', views.sayhello)
]
总结:
路由命名
学习目标:
掌握 总路由与子路由的 命名方法
了解总路由与子路由命名的区别
路由命名
在定义路由的时候,可以为路由命名,方便查找特定视图的具体路径信息。
1) 在使用 include 函数定义路由时,可以使用 namespace 参数定义路由的命名空间,如
url(r'^users/', include('users.urls', namespace='users')),
命名空间表示,凡是 users.urls 中定义的路由,均属于 namespace 指明的 users 名下。
命名空间的作用:避免不同应用中的路由使用了相同的名字发生冲突,使用命名空间区别开。
2) 在定义普通路由时,可以使用 name 参数指明路由的名字,如
urlpatterns = [
url(r'^index/$', views.index, name='index'),
url(r'^say', views.say, name='say'),
]
总结:
Reverse 反解析
学习目标:
知道 reverse 函数的用法, 能够通过 reverse 获取对应的路径
reverse 反解析
使用 reverse 函数,可以根据路由名称,返回具体的路径,如:
from django.urls import reverse # 注意导包路径
def index(request):
url = reverse('usersnamespace:say')
print(url) # 返回 /users/say
return HttpResponse("hello the world!")
def say(request):
return HttpResponse('say')
url = reverse(‘index’)
url = reverse('usersnamespace:say')
路径结尾斜线 / 的说明
Django 中定义路由时,通常以斜线 / 结尾,其好处是用户访问不以斜线 / 结尾的相同路径时,Django 会把用户重定向到以斜线 / 结尾的路径上,而不会返回 404 不存在。如
urlpatterns = [
url(r'^index/$', views.index, name='index'),
]
用户访问 index 或者 index/ 网址,均能访问到 index 视图。
说明:
虽然路由结尾带 / 能带来上述好处,但是却违背了 HTTP 中 URL 表示资源位置路径的设计理念。
是否结尾带 / 以所属公司定义风格为准。
总结:
学习目标:
能够了解 Django 中的 QueryDict 对象
知道 QueryDict 对象的两个调用函数
QueryDict 对象
QueryDict 对象是 django 中一种特殊类型的字典
里面可以存储 一对一类型的数据, 也可以存储 一对多类型的数据
这个对象一般用来存储浏览器传递过来的参数
我们可以默认把他看成是一个字典
但是它和一般的字典的不同之处在于:
获取 QueryDict 中的数据:
例如:
根据一个 key 获取一个值
如果一个键同时拥有多个值将获取最后一个值
# 使用格式:
QueryDict.get(
'键')
# 或可写为:
QueryDict[
'键']
# 例如
QueryDict.get(
'a')
# 获取 a 所对应的一个值.
根据一个 key 获取多个值
根据键获取对应的值,值以列表返回
可以获取指定键的所有值, 如果键不存在则返回空列表 [ ]
# 使用格式:
QueryDict.getlist(
'键')
# 例如
QueryDict.getlist(
'a')
# 获取 a 所对应的所有值.
学习目标:
知道什么是查询字符串
能够获取查询字符串传递的参数
简单理解:
url : http://www.itcast.cn:80/users/index/?a=1&b=2&c=3#id=123
url 地址中以 ? 开始,直到 # 结束的部分, 我们统称为: 查询字符串( QueryString )
获取请求路径中的查询字符串参数(形如 ?k1=v1&k2=v2 )
可以通过 request.GET 属性获取,这个方法返回 QueryDict 对象。
// 前端发送请求:
$.ajax({
url:
'http://127.0.0.1:8000/reqresp/qs/?a=1&b=2&a=3',
type:
'get',
dataType:
'json'
})
.done(
function(data){
console
.log(data)
// 打印: OK
})
.fail(
function(error){
console
.log(error)
})
# python 部分接收发送的参数并打印:
# 视图函数
def qs(request):
# 获取查询字符串参数
a = request.GET.get(
'a')
b = request.GET.get(
'b')
alist = request.GET.getlist(
'a')
# 打印
print(a)
# 3
print(b)
# 2
print(alist)
# ['1', '3']
# 返回响应对象
return
HttpResponse(
'OK')
重要:
查询字符串不区分请求方式,即假使客户端进行 POST 方式的请求,要关闭CSRF后,依然可以通过 request.GET 获取请求中的查询字符串数据。
注意:
学习目标:
了解路径传参的方式和获取方法
在定义路由 URL 时,可以使用正则表达式提取参数的方法从 URL 中获取请求参数,Django 会将提取的参数直接传递到视图的传入参数中。
url(
r'^weather/([a-z]+)/(\d{4})/$', views.weather),
def weather(request, city, year): print(
'city=%s' % city)
print(
'year=%s' % year)
return HttpResponse(
'OK')
url(
r'^weather/(?P, views.weather),
def weather(request, year, city): print(
'city=%s' % city)
print(
'year=%s' % year)
return HttpResponse(
'OK')
学习目标:
了解表单类型传参的获取方法
能够通过对应的方法, 获取表单传递过来的参数
准备工作:
请求体数据格式不固定,可以是表单类型字符串,可以是 JSON 字符串,可以是 XML 字符串,应区别对待。可以发送请求体数据的请求方式有 POST、PUT、PATCH、DELETE。
Django 默认开启了 CSRF 防护,会对上述请求方式进行 CSRF 防护验证,在测试时可以关闭 CSRF 防护机制,方法为在 settings.py 文件中注释掉 CSRF 中间件,如:
转存失败重新上传取消
注释掉后,我们可以进行下面方法的验证, 否则不能成功.
前端发送的表单类型的请求体数据,可以通过 request.POST 属性获取,返回 QueryDict 对象。
我们又知道: QueryDict 对象类似于一个字典, 所以我们可以通过 get( ) 来获取 key 值所对应的 value 值
def get_body(request):
# 获取表单参数
a = request.POST.get(
'a')
b = request.POST.get(
'b')
alist = request.POST.getlist(
'a')
# 打印
print(a)
print(b)
print(alist)
# 返回
return
HttpResponse(
'OK')
例如:
转存失败重新上传取消
总结:
学习目标:
了解非表单类型数据的获取方式
能够获取非表单类型数据
非表单类型的请求体数据,Django 无法自动解析
可以通过 request.body 属性获取最原始的请求体数据,自己按照请求体格式( JSON、XML 等)进行解析。
其中: request.body 返回 bytes 类型。
# 获取方式:
request.body
# 得到的是 bytes 类型数据
# 可以通过 decode() 函数: 将 bytes 转为 str
request.body.decode()
例如:
要获取请求体中的如下 JSON 数据
{
"a":
1,
"b":
2}
可以进行如下方法操作:
import json
def get_body_json(request):
# 获取 json 类型数据:
json_bytes = request.body
# 将 bytes 类型转为 str
json_str = json_bytes.decode()
# python3.6 及以上版本中, json.loads() 方法可以接收 str 和 bytes 类型
#但是 python3.5 以及以下版本中, json.loads() 方法只能接收 str, 所以我们的版本如果是
# 3.5 需要有上面的编码步骤.
req_data = json.loads(json_str)
print(req_data[
'a'])
print(req_data[
'b'])
return
HttpResponse(
'OK')
演示效果:
转存失败重新上传取消
总结:
学习目标:
了解获取请求头信息的方法
可以通过 request.META 属性获取请求头中的数据 request.META 为字典类型
这里需要注意一点是: 我们平常见到的请求头是这样的:
POST /reqresp/req/ HTTP/
1.1
Host:
127.0.0.1:
8000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: dd531a45-
7518-
1e8f-
63a5-be03ed593471
a=
1&b=
2&a=
3
但是我们通过 request.META 获取的时候,需要使用如下所示的用法:
CONTENT_LENGTH
– The length of the request body (as a string).CONTENT_TYPE
– The MIME type of the request body.HTTP_ACCEPT
– Acceptable content types for the response.HTTP_ACCEPT_ENCODING
– Acceptable encodings for the response.HTTP_ACCEPT_LANGUAGE
– Acceptable languages for the response.HTTP_HOST
– The HTTP Host header sent by the client.HTTP_REFERER
– The referring page, if any.HTTP_USER_AGENT
– The client’s user-agent string.QUERY_STRING
– The query string, as a single (unparsed) string.REMOTE_ADDR
– The IP address of the client.REMOTE_HOST
– The hostname of the client.REMOTE_USER
– The user authenticated by the Web server, if any.REQUEST_METHOD
– A string such as "GET"
or "POST"
.SERVER_NAME
– The hostname of the server.SERVER_PORT
– The port of the server (as a string).具体使用如:
def get_headers(request):
# 使用字典的方式获取请求头内部的数据
print(request.META[
'CONTENT_TYPE'])
# 返回
return
HttpResponse(
'OK')
演示:
转存失败重新上传取消
总结:
学习目标:
了解请求头对象 ( request ) 中的其他信息
演示:
转存失败重新上传取消
总结:
学习目标:
知道 HttpResponse 生成对象的三个参数
导入方式:
# 可以从 django.http 里面导入 HttpResponse
fromdjango.http
importHttpResponse
定义形式:
定义格式
:
HttpResponse(
content=
响应体
,
content_type=
响应体数据类型
,
status=
状态码
)
通过上式我们知道 HttpResponse 里面有对应的一些参数可以修改:
例如:
# 定义一个新的视图函数
def demo_response(request):
# 返回一个 HttpResponse 响应对象
return
HttpResponse(
'{"name": "python"}',
content_type=
"application/json",
status=
400)
效果演示:
转存失败重新上传取消
我们会看到响应的内容我们已经获取了, 而且返回回来的状态码也是有的.
特别的使用方式:
我们如果需要在响应头添加自定义的键值对内容,
可以把 HttpResponse 对象当做字典进行响应头键值对的设置:
# 创建一个 response 对象
response = HttpResponse()
# 在对象中添加一个新的 键值对
response[
'Itcast'] =
'Python'
示例:
fromdjango.http
importHttpResponse
# 常规用法:
def demo_view(request):
return
HttpResponse(
'itcast python', status=
400)
# 或者想这样使用:
def demo_view(request):
# 创建一个 response 对象
response = HttpResponse(
'itcast python', status=
400)
# 在 response 对象中添加一个新的键值对
response[
'Itcast'] =
'Python'
# 返回 response
return
response
演示效果:
转存失败重新上传取消
学习目标:
了解 Django 中 HttpResponse 类的子类
知道 HttpResponse 子类的调用形式
Django 提供了一系列 HttpResponse 的子类,可以快速设置状态码
这个状态码可以从 Django.http
里面导入,例如:
# 导入方式:
fromdjango.http
importHttpResponseNotFound
子类有:
使用的演示:
转存失败重新上传取消
学习目标:
了解 JsonResponse 的调用方法和功能
如果我们要返回 json 字符串, 那么我们可以使用 JsonResponse 来帮助我们快速的构建 json 字符串,进行返回.
JsonResponse 能够帮助我们自动把字典转成 json 字符串类型, 并且还不用自己设置响应头中 contentType 字段
所以总结一下, JsonResponse 能够帮助我们做到如下两点:
使用:
# 导入 JsonResponse
fromdjango.http
importJsonResponse
def demo_view(request):
# 直接返回 JsonResponse 这个对象,并且里面可以直接传入参数
return
JsonResponse({
'city':
'beijing',
'subject':
'python'})
显示效果:
转存失败重新上传取消
学习目标:
了解 redirect 函数的使用方法和作用
# 使用格式:
redirect(
'想要跳转的路径')
例如:
fromdjango.shortcuts
importredirect
def demo_view1(request):
# 第一种用法: 直接在 redirect 函数中添加路由字符串
return
redirect(
'/users/index/')
def demo_view2(request):
# 第二种用法: 将 reverse 和 redirect 搭配使用
url = reverse(
'users:index')
return
redirect(url)
演示效果:
转存失败重新上传取消
说明:
Cookie
学习目标:
掌握 Cookie 的定义和使用
Cookie 定义
Cookie,有时也用其复数形式 Cookies,指的是由服务端生成, 保存在客户端的一种数据存储形式, 内部以 key/value 键值对形式存储. 一般不存储敏感信息. 内容有时会被加密.
背景:
Cookie 最早是网景公司的前雇员 Lou Montulli 在 1993 年 3 月的发明。Cookie 是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将 Cookie 的 key/value 保存到某个目录下的文本文件内,下次请求同一网站时就发送该 Cookie 给服务器(前提是浏览器设置为启用 cookie )。Cookie 名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等。服务器可以利用 Cookies 包含信息的任意性来筛选并经常性维护这些信息,以判断在 HTTP 传输中的状态。Cookies 最典型记住用户名。
建议:
Cookie 是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
Cookie 的特点
设置 Cookie
可以通过 HttpResponse 对象中的 set_cookie 方法来设置 cookie。
# 使用方法:
# 创建 response 对象
response = HttpResponse()
# 调用对象的 set_cookie() 函数
response.set_cookie(key, value, max_age)
参数解析:
key: cookie 中保存信息的名称
value: cookie 中保存信息时, 名称对应的值部分
max_age: cookie 中保存信息的有效期, 超过有效期, key-value 失效
其中 max_age 单位为秒, 默认为 None. 如果设置 None 值, 则关闭浏览器失效.
例如:
response.set_cookie('itcast', 'python', max_age=3600)
读取 Cookie
可以通过 HttpRequest 对象( request )的 COOKIES 属性来读取本次请求携带的 cookie 值。
# 使用方法:
# 其中: request.COOKIES 为字典类型
value = request.COOKIES.get('key')
request.COOKIES 为字典类型, 可以使用字典的 get( )
例如:
value = request.COOKIES.get('itcast') # python
总结:
Session
学习目标:
了解和知道 session 的作用和特点
Session 了解
Session 是一种会话控制方式. 由服务端创建, 并且保存在服务端的数据存储形式. 内部以 key/value 键值对的形式存储. 可以存储敏感信息, 内容有些会被加密. 一般生成 session 后, 我们会把 sessionid 传递给 cookie 保存.
Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的 Web 页时,如果该用户还没有会话,则 Web 服务器将自动创建一个 Session 对象。
当会话过期或被放弃后,服务器将终止该会话。Session 对象最常见的一个用法就是存储用户信息。
Session 的作用
Session 的特点
总结:
学习目标:
知道和了解 session 的配置和存储
Django 项目默认启用 Session
可以在 settings.py 文件中查看,如图所示
转存失败重新上传取消
如需禁用 session,将上图中的 session 中间件注释掉即可。
在 settings.py 文件中,可以设置 session 数据的存储方式,可以保存在数据库、本地缓存等。
数据库
默认存储方式
存储在数据库中,如下设置可以写,也可以不写
SESSION_ENGINE=
'django.contrib.sessions.backends.db'
如果存储在数据库中,需要在项 INSTALLED_APPS 中安装 Session 应用。
转存失败重新上传取消
数据库中的表如图所示
转存失败重新上传取消
表结构如下
转存失败重新上传取消
由表结构可知,操作 Session 包括三个数据:键,值,过期时间。
本地缓存
存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。
SESSION_ENGINE=
'django.contrib.sessions.backends.cache'
混合存储
优先从本机内存中存取,如果没有则从数据库中存取。
SESSION_ENGINE=
'django.contrib.sessions.backends.cached_db'
Redis
在 redis 中保存 session,需要引入第三方扩展,我们可以使用 django-redis 来解决。
1) 安装扩展
pip install django-redis
2)配置
在 settings.py 文件中做如下设置
CACHES = {
"default"
: {
"BACKEND"
:
"django_redis.cache.RedisCache",
"LOCATION"
:
"redis://127.0.0.1:6379/1",
"OPTIONS"
: {
"CLIENT_CLASS"
:
"django_redis.client.DefaultClient",
}
}
}
SESSION_ENGINE =
"django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS =
"default"
注意
如果 redis 的 ip 地址不是本地回环 127.0.0.1, 而是其他地址,访问 Django 时,可能出现 Redis 连接错误,如下:
转存失败重新上传取消
解决方法:
修改 redis 的配置文件,添加特定 ip 地址。
打开 redis 的配置文件
sudo vim /etc/redis/redis.conf
在如下配置项进行修改(如要添加 10.211.55.5 地址)
转存失败重新上传取消
重新启动 redis 服务
sudo service redis-server restart
Session 相关操作
学习目标:
掌握 session 的储存和读取操作
Session 操作
通过 HttpRequest 对象( request ) 的 session 属性进行会话的读写操作。
1)往 session 中写入键值对:
# 使用格式:
request.session['键'] = 值
2)根据 key 读取 session 中的数据:
# 使用格式:
value = request.session.get('键',默认值)
3)清除所有 session,在存储中删除值部分:
# 使用格式:
request.session.clear()
4)清除 session 数据,在存储中删除 session 的整条数据:
# 使用格式:
request.session.flush()
5)删除 session 中的指定键及值,在存储中只删除某个键及对应的值。
# 使用格式:
del request.session['键']
6)设置 session 的有效期
# 使用格式:
request.session.set_expiry(value)
总结:
类视图
学习目标:
知道什么是类视图
能够调用类视图
类视图引入
在 Django 中, 以函数的方式定义的视图称为 函数视图 也可以使用类来定义一个视图,称为 类视图
函数视图遇到一个视图对应的路径提供了多种不同 HTTP 请求方式的支持时
便需要在一个函数中编写不同的业务逻辑,代码可读性与复用性都不佳
例如:
def register(request):
"""处理注册"""
# 获取请求方法,判断是 GET/POST 请求
if request.method == 'GET':
# 处理 GET 请求,返回注册页面
return render(request, 'register.html')
else:
# 处理 POST 请求,实现注册逻辑
return HttpResponse('这里实现注册逻辑')
使用类视图可以将视图对应的不同请求方式以类中的不同方法来区别定义。如下所示
from django.views.generic import View
class RegisterView(View):
"""类视图:处理注册"""
def get(self, request):
"""处理 GET 请求,返回注册页面"""
return render(request, 'register.html')
def post(self, request):
"""处理 POST 请求,实现注册逻辑"""
return HttpResponse('这里实现注册逻辑')
类视图的好处:
类视图使用
定义类视图需要继承自 Django 提供的父类 View ,可使用 from django.views.generic import View 或者 from django.views.generic.base import View 导入,定义方式如上所示。
注意 : 配置路由时,需要在类名后面增加 as_view( ) 函数
urlpatterns = [
# 视图函数:路由添加
# url(r'^register/$', views.register),
# 类视图:路由添加
url(r'^register/$', views.RegisterView.as_view()),
]
演示效果:
转存失败重新上传取消
转存失败重新上传取消
总结:
类视图原理
学习目标:
了解类视图的底层原理
类视图原理
为什么我们定义 url 的时候, 调用 as_view( ) 函数,就可以达到结果, 如果不调用就会报错.
到底 as_view( ) 帮助我们干了什么了?
我们下面来研究一下:
@classonlymethod
def as_view(cls, **initkwargs):
...省略代码...
def view(request, *args, **kwargs):
# 这里的cls是as_view这个函数接收的第一个参数,也就是调用当前函数的类.
# 得到调用的类了之后, 创建类的对象: self
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
# 给当前这个类,添加对应的属性, 如下所示:
self.request = request
self.args = args
self.kwargs = kwargs
# 调用dispatch方法,按照不同请求方式调用不同请求方法
return self.dispatch(request, *args, **kwargs)
...省略代码...
# 返回真正的函数视图
return view
# dispatch 帮我们判断了 前端发送的请求方法 ( get )是否在 django 的规定范围内,
# 如果在, 则调用该方法.
def dispatch(self, request, *args, **kwargs):
# self.http_method_names 指的是我们的类视图中,对象方法的名字
# 这里把所有方法的名字都存放在了 http_methods_names 中
# 我们会把当前请求的方式转为小写,然后判断是否在列表中存在.
if request.method.lower() in self.http_method_names:
# 如果在里面, 则进入这里
# 这里的 getattr 作用是获取当前对象的属性.
# 下面的参数为:
# self : 类视图对象
# request.method.lower() : 请求方法的小写. 例如: 'get' 或 'post'
# http_method_not_allowed : 默认值, 如果上面的值没有的话, 把该值给 handle
# 下面代码整体的意思: 根据类视图对象, 获取当前类视图中对应名称的方法
# 如果获取到, 则把方法返回给handle, 否则不允许访问.
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
# 如果类视图中如果没有的话, 则进入这里, 表明不允许进行请求.
# 我们会把不允许请求这个字段返回给handle.
handler = self.http_method_not_allowed
# 最终返回handle(handle里面要么包含可以访问的方法, 要么就是不允许访问的字段)
return handler(request, *args, **kwargs)
总结:
学习目标:
能够给类视图中的函数增加装饰器
准备工作:
定义一个装饰器函数, 以及我们将要访问的类视图函数:
目标: 给类视图的两个函数, 添加上定义的装饰器函数
# 我们自定义的装饰器:
def my_decorator(func):
def wrapper(request, *args, **kwargs):
print(
'自定义装饰器被调用了')
print(
'请求路径%s'% request.path)
return
func(request, *args, **kwargs)
return
wrapper
# 自定义的类视图:
class DemoView(View):
def get(self, request):
print(
'类视图中的 get 方法')
return
HttpResponse(
'demoview get')
def post(self, request):
print(
'类视图中的 post 方法')
return
HttpResponse(
'demoview post')
在 URL 配置, 间接给函数增加装饰器:
urlpatterns = [
# 类视图对应的子路由:
url(
r'^demo/$', my_decorate(DemoView.as_view()))
]
此种方式最简单,但因装饰行为被放置到了 url 配置中,单看视图的时候无法知道此视图还被添加了装饰器,不利于代码的有效阅读. 故. 此方法不建议使用.
此种方式会为类视图中的所有请求方法都加上装饰器行为 (因为是在视图入口处,分发请求方式前)
在类视图中使用为函数视图准备的装饰器时,不能直接添加装饰器
需要使用 method_decorator 将其转换为适用于类视图方法的装饰器.
fromdjango.utils.decorators
importmethod_decorator
# 为特定请求方法添加装饰器
class DemoView(View):
@method_decorator(my_decorator) # 为 get 方法添加了装饰器
def get(self, request):
print(
'类视图中的 get 方法')
return
HttpResponse(
'demoview get')
@method_decorator(my_decorator) # 为 post 方法添加了装饰器
def post(self, request):
print(
'类视图中的 post 方法')
return
HttpResponse(
'demoview post')
def put(self, request):
# 没有为 put 方法添加装饰器
print(
'类视图中的 put 方法')
return
HttpResponse(
'demoview put')
还可以这样用:
method_decorator装饰器使用 name 参数指明被装饰的方法
# 为特定请求方法添加装饰器
@method_decorator(my_decorator, name='get')
class DemoView(View):
def get(self, request):
print(
'类视图中的 get 方法')
return
HttpResponse(
'demoview get')
def post(self, request):
print(
'类视图中的 post 方法')
return
HttpResponse(
'demoview post')
# 为全部请求方法添加装饰器
@method_decorator(my_decorator, name='dispatch')
class DemoView(View):
def get(self, request):
print(
'类视图中的 get 方法')
return
HttpResponse(
'demoview get')
def post(self, request):
print(
'类视图中的 post 方法')
return
HttpResponse(
'demoview post')
类视图 Mixin 扩展类
学习目标:
知道 Mixin 扩展类的定义和使用
Mixin 扩展类的使用
例如:
# 我们自定义的装饰器:
def my_decorator_1(func):
def wrapper(request, *args, **kwargs):
print('自定义装饰器被调用了')
print('请求路径%s' % request.path)
return func(request, *args, **kwargs)
return wrapper
# 定义的 Mixin 扩展类:
class FirstMixin(object):
@classmethod
def as_view(cls, *args, **kwargs):
view = super().as_view(*args, **kwargs)
view = my_decorator_1(view)
return view
# 定义的类视图, 继承自: 扩展类 + View
class DemoView(FirstMixin, View):
def get(self, request):
print('demoview get')
return HttpResponse('demoview get')
def post(self, request):
print('demoview post')
return HttpResponse('demoview post')
多个 Mixin 扩展类连用:
例如:
# 我们自定义的装饰器:
def my_decorator_1(func):
def wrapper(request, *args, **kwargs):
print('自定义装饰器被调用了')
print('请求路径%s' % request.path)
return func(request, *args, **kwargs)
return wrapper
# 我们自定义的装饰器:
def my_decorator_2(func):
def wrapper(request, *args, **kwargs):
print('自定义装饰器被调用了')
print('请求路径%s' % request.path)
return func(request, *args, **kwargs)
return wrapper
class FirstMixin(object):
""" FirstMixin 扩展类 """
@classmethod
def as_view(cls, *args, **kwargs):
view = super().as_view(*args, **kwargs)
view = my_decorator_1(view)
return view
class SecondMixin(object):
""" SecondMixin 扩展类 """
@classmethod
def as_view(cls, *args, **kwargs):
view = super().as_view(*args, **kwargs)
view = my_decorator_2(view)
return view
class DemoView(FirstMixin, SecondMixin, View):
def get(self, request):
print('demoview get')
return HttpResponse('demoview get')
def post(self, request):
print('demoview post')
return HttpResponse('demoview post')
定义的扩展父类名称通常以 Mixin 结尾
总结:
学习目标:
知道什么是中间件
掌握中间件的调用顺序
定义一个中间件工厂函数,然后返回一个可以被调用的中间件。
中间件工厂函数需要接收一个可以调用的 get_response 对象。
返回的中间件也是一个可以被调用的对象,并且像视图一样需要接收一个 request 对象参数,返回一个 response 对象。
def simple_middleware(get_response):
# 此处编写的代码仅在 Django 第一次配置和初始化的时候执行一次。
def middleware(request):
# 此处编写的代码会在每个请求处理视图前被调用。
response = get_response(request)
# 此处编写的代码会在每个请求处理视图之后被调用。
return
response
return
middleware
例如,在 users 应用中新建一个 middleware.py 文件,
def my_middleware(get_response):
print(
'init 被调用')
def middleware(request):
print(
'before request 被调用')
response = get_response(request)
print(
'after response 被调用')
return
response
return
middleware
定义好中间件后,需要在 settings.py 文件中添加注册中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware'
,
'django.contrib.sessions.middleware.SessionMiddleware'
,
'django.middleware.common.CommonMiddleware'
,
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
# 添加中间件
'users.middleware.my_middleware'
,
]
定义一个视图进行测试
def demo_view(request):
print(
'view 视图被调用')
return
HttpResponse(
'OK')
执行结果
转存失败重新上传取消
注意:Django 运行在调试模式下,中间件 init 部分有可能被调用两次。
转存失败重新上传取消
示例:
定义两个中间件
def my_middleware(get_response):
print(
'init 被调用')
def middleware(request):
print(
'before request 被调用')
response = get_response(request)
print(
'after response 被调用')
return
response
return
middleware
def my_middleware2(get_response):
print(
'init2 被调用')
def middleware(request):
print(
'before request 2 被调用')
response = get_response(request)
print(
'after response 2 被调用')
return
response
return
middleware
注册添加两个中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware'
,
'django.contrib.sessions.middleware.SessionMiddleware'
,
'django.middleware.common.CommonMiddleware'
,
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
'users.middleware.my_middleware'
,
# 添加
'users.middleware.my_middleware2'
,
# 添加
]
执行结果
init2
被调用
init
被调用
before request
被调用
before request
2
被调用
view
视图被调用
after response
2
被调用
after response
被调用
视图前后的执行流程
转存失败重新上传取消
学习目标:
掌握 django 自带模板路径的添加方法
能够调用 django 中的模板
在工程中创建模板目录 templates
在 settings.py 配置文件中修改 TEMPLATES 配置项的 DIRS 值:
由原来的代码:
TEMPLATES = [
{
'BACKEND'
:
'django.template.backends.django.DjangoTemplates',
'DIRS'
: [],
# 需要在此处添加模板路径
'APP_DIRS'
:
True,
'OPTIONS'
: {
'context_processors'
: [
'django.template.context_processors.debug'
,
'django.template.context_processors.request'
,
'django.contrib.auth.context_processors.auth'
,
'django.contrib.messages.context_processors.messages'
,
],
},
},
]
改为如下代码:
TEMPLATES = [
{
'BACKEND'
:
'django.template.backends.django.DjangoTemplates',
'DIRS'
: [os.path.join(BASE_DIR,
'templates')],
# 在此处拼接模板路径
'APP_DIRS'
:
True,
'OPTIONS'
: {
'context_processors'
: [
'django.template.context_processors.debug'
,
'django.template.context_processors.request'
,
'django.contrib.auth.context_processors.auth'
,
'django.contrib.messages.context_processors.messages'
,
],
},
},
]
在 templates 目录中新建一个模板文件,如 index.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
Title
title>
head>
<body>
body>
html>
Django 提供了一个实现模板渲染的函数 render( )
使用:
# 使用方式:
render( request,
'模板文件名称',
添加给模板的数据
)
参数解释:
request 是需要要添加的一个参数, 这个参数规定死了就是 request
模板文件名称: 主要指我们在 templates 中添加的前端文件名称
第三个参数主要是: 传给模板的一些变量. 一般我们使用字典的格式
例如:
fromdjango.shortcuts
importrender
def index(request):
# 定义一个变量, 拼接为字典格式:
context={
'city':
'北京'}
# 返回 render() 函数
return
render(request,
'index.html',context)
模板中也可以添加变量:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
Title
title>
head>
<body>
<h1>
{{ city }}
h1>
body>
html>
学习目标:
了解模板变量和模板语句的书写格式
变量名必须由字母、数字、下划线(不能以下划线开头)和点组成 。
# 语法如下:
{{
变量
}}
模板变量可以是 python 的内建类型
例如:
def demo(request):
context = {
'city'
:
'北京',
'adict'
: {
'name'
:
'西游记',
'author'
:
'吴承恩'
},
'alist'
: [
1,
2,
3,
4,
5]
}
return
render(request,
'index.html', context)
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
Title
title>
head>
<body>
<h1>
{{ city }}
h1>
<h1>
{{ adict }}
h1>
<h1>
{{ adict.name }}
h1>
<h1>
{{ alist }}
h1>
<h1>
{{ alist.0 }}
h1>
body>
html>
for 循环:
{%
foritem
in
列表
%}
循环逻辑
{{forloop.counter}}
表示当前是第几次循环,从
1开始
{%empty%}
列表为空或不存在时执行此逻辑
{% endfor %}
if 条件:
{%
if... %}
逻辑
1
{%
elif... %}
逻辑
2
{%
else%}
逻辑
3
{% endif %}
比较运算符如下:
==
!=
<
>
<=
>=
逻辑运算符如下:
用于连接比较运算符
and
or
not
例如:
后端代码:
def temp(request):
context = {
'item'
:[
1,
2,
3,
4]
}
return
render(request,
'index.html', context)
前端代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
Title
title>
head>
<body>
{% for i in item %}
{% if forloop.counter == 1 or forloop.counter == 2 %}
{{i}} if
语句进入
<br>
{% endif %}
{% empty %}
item
值为空
{% endfor %}
body>
html>
显示结果:
1 if
语句进入
2 if
语句进入
注意:运算符左右两侧不能紧挨变量或常量,必须有空格.
{%
ifa ==
1%}
# 正确写法
{%
ifa==
1%}
# 错误写法
过滤器
学习目标:
能够掌握过滤器对应的语法规则
过滤器语法:
# 语法如下:
变量 | 过滤器:参数
参数如下:
常见过滤器介绍:
列举自带过滤器几个如下:
总结:
自定义过滤器
学习目标:
掌握自定义过滤器的使用
自定义过滤器的创建
在自己的 app 里建一个 templatetags 包,在包里创建一个用于定义的 py 文件
转存失败重新上传取消
转存失败重新上传取消
注意点:
templatetags 文件夹 要在各自的应用内创建
当前子应用一定要在 settings.py 的 INSTALL_APPS 模块中注册.
总结:
模板继承
学习目标:
掌握模板继承的特点和使用方式
父模板
如果发现在多个模板中某些内容相同,那就应该把这段内容抽取出来放到父模板中.
标签 block:用于在父模板中预留区域,留给子模板填充差异性的内容,名字不能相同。
为了更好的可读性,建议给 endblock 标签写上名字,这个名字与对应的 block 名字相同。
父模板中也可以使用上下文中传递过来的数据。
{% block 名称 %}
预留区域,可以编写默认内容,也可以没有默认内容
{% endblock 名称 %}
子模板
标签 extends:继承,写在子模板文件的第一行。
{% extends "父模板路径"%}
子模版不用填充父模版中的所有预留区域,如果子模版没有填充,则使用父模版定义的默认值。
填充父模板中指定名称的预留区域。
{% block 名称 %}
实际填充内容
{{ block.super }}用于获取父模板中block的内容
{% endblock 名称 %}
总结:
注释
学习目标:
掌握单行和多行注释的写法
单行注释:
单行注释语法如下:
# 语法如下
{# 注释内容 #}
多行注释:
多行注释使用 comment 标签,语法如下:
# 语法如下
{% comment %}
注释内容
{% endcomment %}
总结:
Jinja2 模板在 Django 中使用
学习目标:
了解 jinja2 的使用方法
能够使用 jinja2 在 django 中渲染数据
jinja2 介绍
Jinja2:是 Python 下一个被广泛应用的模板引擎,是由 Python 实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,尤其是 Flask 框架内置的模板语言
由于 django 默认模板引擎功能不齐全,速度慢,所以我们也可以在 Django 中使用 jinja2, jinja2 宣称比 django 默认模板引擎快 10-20 倍。
Django 主流的第三方 APP 基本上也都同时支持 Django 默认模板及 jinja2,所以要用 jinja2 也不会有多少障碍。
安装 jinja2 模块
# 安装 jinja2 模板
pip install jinja2
Django 配置 jinja2
在项目文件中创建 jinja2_env.py 文件, 进行配置
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
return env
添加配置文件后, 在 settings.py 文件中添加, 告知 django 配置文件路径:
TEMPLATES = [
{
# 将默认的模板渲染引擎改为 jinja2 引擎
'BACKEND': 'django.template.backends.jinja2.Jinja2',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS':True,
'OPTIONS':{
# 添加配置文件路径:
'environment': 'jinja2_env.environment',
'context_processors':[
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
jinja2 模板的使用绝大多数和 Django 自带模板一样
for 循环有差异
转存失败重新上传取消
jinja2 自定义过滤器
在 jinja2_env.py 文件中自定义过滤器
from jinja2 import Environment
def environment(**options):
env = Environment(**options)
# 2.将自定义的过滤器添加到环境中
env.filters['do_listreverse'] = do_listreverse
return env
# 1.自定义过滤器
def do_listreverse(li):
if li == "B":
return "哈哈"
总结:
学习目标:
掌握 CSRF 的攻击方式和防御方式
CSRF
全拼为 Cross Site Request Forgery
, 译为跨站请求伪造。CSRF
指攻击者盗用了你的身份,以你的名义发送恶意请求。
转存失败重新上传取消
步骤
转存失败重新上传取消
CSRF_TOKEN 的设置过程
转存失败重新上传取消
数据库映射
学习目标:
掌握 ORM 框架的概念和作用
ORM 框架
O是 object,也就类对象的意思
R 是 relation,翻译成中文是关系, 也就是关系数据库中数据表的意思.
M 是 mapping,是映射的意思.
在 ORM 框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。
ORM 框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
django 中内嵌了 ORM 框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
使用 django 进行数据库开发的步骤如下:
ORM作用
转存失败重新上传取消
转存失败重新上传取消
数据库配置
学习目标:
掌握在 django 中使用数据库的配置
修改默认配置
在 settings.py 中保存了数据库的连接配置信息,Django 默认初始配置使用 sqlite 数据库
修改为 Mysql 数据库配置:
使用 MySQL 数据库首先需要安装驱动程序
pip install PyMySQL
在 Django 的工程同名子目录的 __init__.py 文件中添加如下语句
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
作用是让 Django 的 ORM 能以 mysqldb 的方式来调用 PyMySQL。
总结:
定义模型类
学习目标:
能够在项目中定义模型类
定义模型类的步骤:
接下来首先以"图书-英雄"管理为例进行演示.
演示:
创建子应用 booktest,在 models.py 文件中定义模型类.
from django.db import models
# 定义图书模型类 BookInfo
class BookInfo(models.Model):
btitle = models.CharField(max_length=20, verbose_name='名称')
bpub_date = models.DateField(verbose_name='发布日期')
bread = models.IntegerField(default=0, verbose_name='阅读量')
bcomment = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'tb_books' # 指明数据库表名
verbose_name = '图书' # 在admin站点中显示的名称
verbose_name_plural = verbose_name # 显示的复数名称
def __str__(self):
"""定义每个数据对象的显示信息"""
return self.btitle
# 定义英雄模型类 HeroInfo
class HeroInfo(models.Model):
GENDER_CHOICES = (
(0, 'female'),
(1, 'male')
)
hname = models.CharField(max_length=20, verbose_name='名称')
hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息')
hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'tb_heros'
verbose_name = '英雄'
verbose_name_plural = verbose_name
def __str__(self):
return self.hname
1) 数据库表名
模型类如果未指明表名,Django 默认以 小写 app应用名_小写模型类名 为数据库表名。
可通过 db_table 指明数据库表名。
2) 关于主键
django 会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后 django 不会再创建自动增长的主键列。
默认创建的主键列属性为 id,可以使用 pk 代替,pk 全拼为 primary key。
3) 属性命名限制
4)字段类型
类型 |
说明 |
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是相互排斥的,组合将会发生错误 |
TimeField |
时间,参数同DateField |
DateTimeField |
日期时间,参数同DateField |
FileField |
上传文件字段 |
ImageField |
继承于FileField,对上传的内容进行校验,确保是有效的图片 |
5) 选项
选项 |
说明 |
null |
如果为True,表示允许为空,默认值是False |
blank |
如果为True,则该字段允许为空白,默认值是False |
db_column |
字段的名称,如果未指定,则使用属性的名称 |
db_index |
若值为True, 则在表中会为此字段创建索引,默认值是False |
default |
默认 |
primary_key |
若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用 |
unique |
如果为True, 这个字段在表中必须有唯一值,默认值是False |
related_name |
在关联查询中,代替单一对象查找多对象 对象名小写_set(book.heroinfo_set.all() 的写法 |
auto_now_add |
只在数据添加的时候,记录时间 |
auto_now |
数据添加和更新的时候,记录时间 |
null 是数据库范畴的概念,blank 是表单验证范畴的
6) 外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
迁移
将模型类同步到数据库中。
1)生成迁移文件
python manage.py makemigrations
2)同步到数据库中
python manage.py migrate
添加测试数据
insert into tb_books(btitle,bpub_data,bread,bcomment,is_delete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0);
insert into tb_heros(hname,hgender,hbook_id,hcomment,is_delete) values
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);
总结:
Shell 演示工具使用
学习目标:
了解 shell 工具的使用方式
shell工具
Django 的 manage 工具提供了 shell 命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试 python 语句。
通过如下命令进入 shell
python manage.py shell
转存失败重新上传取消
导入两个模型类,以便后续使用
from booktest.models import BookInfo, HeroInfo
查看 MySQL 数据库日志
查看 mysql 数据库日志可以查看对数据库的操作记录。 mysql 日志文件默认没有产生,需要做如下配置:
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
转存失败重新上传取消
把68,69行前面的#去除,然后保存并使用如下命令重启mysql服务。
sudo service mysql restart
使用如下命令打开 mysql 日志文件。
tail -f /var/log/mysql/mysql.log # 可以实时查看数据库的日志内容
# 如提示需要sudo权限,执行
# sudo tail -f /var/log/mysql/mysql.log
总结:
学习目标:
知道数据库操作中增加的两种方法
增加数据有两种方法
save
通过创建模型类对象,执行对象的save()方法保存到数据库中。
>>> fromdatetime
importdate
>>> book = BookInfo(
btitle=
'西游记',
bpub_date=date(
1988,
1,
1),
bread=
10,
bcomment=
10
)
>>> book.save()
>>> hero = HeroInfo(
hname=
'孙悟空',
hgender=
0,
hbook=book
)
>>> hero.save()
>>> hero2 = HeroInfo(
hname=
'猪八戒',
hgender=
0,
hbook_id=book.id
)
>>> hero2.save()
create
通过 模型类.objects.create( ) 保存.
>>> HeroInfo.objects.create(
hname=
'沙悟净',
hgender=
0,
hbook=book
)
沙悟净
>
删除
学习目标:
掌握删除的两种方法
删除的第一种方法:
删除有两种方法
使用对象删除
# 使用模板:
对象.delete()
例如:
# 获取对象:
hero = HeroInfo.objects.get(id=13)
# 调用对象的删除方法:
hero.delete()
删除的第二种方法:
使用查询集删除
# 使用查询集删除:
模型类.objects.filter().delete( )
例如:
HeroInfo.objects.filter(id=14).delete()
总结:
学习目标:
掌握修改的两种方法
修改更新有两种方法
save
修改模型类对象的属性,然后执行 save() 方法
# 使用方式:
对象
.save()
例如:
hero = HeroInfo.objects.get(hname=
'猪八戒')
hero.hname =
'猪悟能'
hero.save()
update
# 使用方式:
查询集
.update()
例如:
使用 模型类.objects.filter().update(),会返回受影响的行数
HeroInfo.objects.filter(hname=
'沙悟净').update(hname=
'沙僧')
查询
学习目标:
掌握查询的相关操作
基本查询
get 查询单一结果,如果不存在会抛出 模型类.DoesNotExist 异常.
all 查询多个结果。
count 查询结果数量。
>>> BookInfo.objects.all()
>>> book = BookInfo.objects.get(btitle='西游记')
>>> book.id
5
>>> BookInfo.objects.get(id=3)
>>> BookInfo.objects.get(pk=3)
>>> BookInfo.objects.get(id=100)
Traceback (most recent call last):
File "
File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/query.py", line 380, in get
self.model._meta.object_name
db.models.DoesNotExist: BookInfo matching query does not exist.
>>> BookInfo.objects.count()
6
总结:
学习目标:
掌握过滤查询的各种方法
实现 SQL 中的 where 功能,包括
对于过滤条件的使用,上述三个方法相同,故仅以 filter 进行讲解。
过滤条件的表达语法如下:
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
属性名称
__
比较运算符
=
值
相等
exact:表示判等。
例:查询编号为1的图书。
BookInfo.objects.filter(id__exact=1)
可简写为:
BookInfo.objects.filter(id=1)
模糊查询
contains:是否包含。
说明:如果要包含%无需转义,直接写即可。
例:查询书名包含'传'的图书。
BookInfo.objects.filter(btitle__contains=
'传')
startswith、endswith:以指定值开头或结尾。
例:查询书名以'部'结尾的图书
BookInfo.objects.filter(btitle__endswith=
'部')
以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
空查询
isnull:是否为null
例:查询书名不为空的图书。
BookInfo.objects.filter(btitle__isnull=
False)
范围查询
in:是否包含在范围内
例:查询编号为1或3或5的图书
BookInfo.objects.filter(id__in=[
1,
3,
5])
比较查询
例:查询编号大于3的图书
BookInfo.objects.filter(id__gt=
3)
不等于的运算符,使用exclude()过滤器。
例:查询编号不等于3的图书
BookInfo.objects.exclude(id=
3)
日期查询
year、month、day、
week_day、hour、minute、second:
对日期时间类型的属性进行运算
例:查询1980年发表的图书。
BookInfo.objects.filter(bpub_date__year=
1980)
例:查询1980年1月1日后发表的图书。
BookInfo.objects.filter(bpub_date__gt=date(
1990,
1,
1))
学习目标:
知道 F 对象和 Q 对象的使用方式
之前的查询都是对象的属性与常量值比较,两个属性怎么比较呢?
答:使用 F对象,被定义在 django.db.models 中.
# 语法如下:
F(
属性名
)
例:查询阅读量大于等于评论量的图书.
# 导入:
fromdjango.db.models
importF
# 查询时使用 F 对象
BookInfo.objects.filter(bread__gte=F(
'bcomment'))
可以在 F 对象 上使用算数运算.
例:查询阅读量大于2倍评论量的图书。
BookInfo.objects.filter(bread__gt=F(
'bcomment') *
2)
多个过滤器逐个调用表示 逻辑与 关系
同 sql 语句中 where 部分的 and 关键字.
例:查询阅读量大于20,并且编号小于3的图书。
BookInfo.objects.filter(bread__gt=
20,id__lt=
3)
或
BookInfo.objects.filter(bread__gt=
20).filter(id__lt=
3)
使用 Q( ) 对象结合|运算符实现 逻辑或(or) 的查询
Q对象 被义在 django.db.models 中.
语法如下:
Q(
属性名
__
运算符
=
值
)
例:查询阅读量大于 20的图书,改写为 Q对象 如下.
# 导入
fromdjango.db.models
importQ
# 获取数据
BookInfo.objects.filter(Q(bread__gt=
20))
Q对象 可以使用 &、|连接,&表示逻辑与,|表示逻辑或.
例:查询阅读量大于20,或编号小于3的图书,只能使用Q对象实现
BookInfo.objects.filter(Q(bread__gt=
20) | Q(pk__lt=
3))
Q对象 前可以使用~操作符,表示非not.
例:查询编号不等于3的图书。
BookInfo.objects.filter(~Q(pk=
3))
聚合函数和排序
学习目标:
知道聚合函数和排序的使用方法
聚合函数
使用 aggregate( ) 过滤器调用聚合函数.
聚合函数包括:
Avg 平均,
Count 数量,
Max 最大,
Min 最小,
Sum 求和
被定义在 django.db.models 中.
例:查询图书的总阅读量.
from django.db.models import Sum
BookInfo.objects.aggregate(Sum('bread'))
注意 aggregate 的返回值是一个字典类型,格式如下:
{'属性名__聚合类小写':值}
如:{'bread__sum':3}
使用 count 时一般不使用 aggregate( ) 过滤器.
例:查询图书总数。
BookInfo.objects.count()
注意 count 函数的返回值是一个数字.
排序
使用 order_by 对结果进行排序
BookInfo.objects.all().order_by('bread') # 升序
BookInfo.objects.all().order_by('-bread') # 降序
总结:
关联查询
学习目标:
掌握关联查询的各种访问方法
由一到多的访问
使用格式:
一对应的模型类对象.多对应的模型类名小写_set
例:
b = BookInfo.objects.get(id=1)
# 套用上面的格式:
b.heroinfo_set.all()
# 如果在
# hbook = models.ForeignKey(BookInfo, related_name="heros")
# 可以替换成 b.heros.all()
由多到一的访问
使用格式:
多对应的模型类对象.外键名
例:
h = HeroInfo.objects.get(id=1)
# 套用上面的格式:
h.hbook
访问一对应的模型类关联对象的 id
使用格式:
多对应的模型类对象.关联类属性_id
例:
h = HeroInfo.objects.get(id=1)
# 套用上面的格式:
h.hbook_id
关联过滤查询
由多模型类条件查询一模型类数据:
语法如下:
关联模型类名小写__属性名__条件运算符=值
注意:如果没有"__运算符"部分,表示等于.
例:
查询图书,要求图书英雄为"孙悟空"
BookInfo.objects.filter(heroinfo__hname='孙悟空')
查询图书,要求图书中英雄的描述包含"八"
BookInfo.objects.filter(heroinfo__hcomment__contains='八')
由一模型类条件查询多模型类数据:
语法如下:
一模型类关联属性名__一模型类属性名__条件运算符=值
注意:如果没有"__运算符"部分,表示等于。
例:
查询书名为“天龙八部”的所有英雄。
HeroInfo.objects.filter(hbook__btitle='天龙八部')
查询图书阅读量大于30的所有英雄
HeroInfo.objects.filter(hbook__bread__gt=30)
总结:
学习目标:
知道查询集的概念和特点
Django 的 ORM 中存在查询集的概念。
查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。
当调用如下过滤器方法时,Django 会返回查询集(而不是简单的列表):
对查询集可以再次调用过滤器进行过滤,如
BookInfo.objects.filter(bread__gt=
30).order_by(
'bpub_date')
也就意味着查询集可以含有零个、一个或多个过滤器。过滤器基于所给的参数限制查询的结果。
从 SQL 的角度讲,查询集与 select 语句等价,过滤器像 where、limit、order by 子句。
判断某一个查询集中是否有数据:
惰性执行
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用
例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集qs
qs = BookInfo.objects.all()
继续执行遍历迭代操作后,才真正的进行了数据库的查询
forbook
inqs:
print(book.btitle)
缓存
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
情况一:如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。
frombooktest.models
importBookInfo
[book.id
forbook
inBookInfo.objects.all()]
[book.id
forbook
inBookInfo.objects.all()]
转存失败重新上传取消
转存失败重新上传取消
情况二:经过存储后,可以重用查询集,第二次使用缓存中的数据。
qs=BookInfo.objects.all()
[book.id
forbook
inqs]
[book.id
forbook
inqs]
转存失败重新上传取消
转存失败重新上传取消
可以对查询集进行取下标或切片操作,等同于 sql 中的 limit 和 offset 子句。
注意:不支持负数索引。
对查询集进行切片后返回一个新的查询集,不会立即执行查询。
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发 IndexError 异常,[0:1].get() 如果没有数据引发 DoesNotExist 异常。
示例:获取第1、2项,运行查看。
qs = BookInfo.objects.all()[
0:
2]
管理器 Manager
学习目标:
掌握管理器的相关知识
管理器简介
BookInfo.objects.get( id = 2)
管理器是 Django 的模型进行数据库操作的接口
Django 应用的每个模型类都拥有至少一个管理器。
我们在通过模型类的 objects 属性提供的方法操作数据库时,即是在使用一个管理器对象 objects。
当没有为模型类定义管理器时,Django 会为每一个模型类生成一个名为 objects 的管理器,它是 models.Manager 类的对象。
自定义管理器
我们可以自定义管理器,并应用到我们的模型类上。
注意:一旦为模型类指明自定义的管理器后,Django 不再生成默认管理对象 objects.
自定义管理器类主要用于两种情况:
1. 修改原始查询集,重写 all() 方法。
a)打开 booktest / models.py 文件,定义类 BookInfoManager
#图书管理器
class BookInfoManager(models.Manager):
def all(self):
#默认查询未删除的图书信息
#调用父类的成员语法为:super().方法名
return super().filter(is_delete=False)
b)在模型类BookInfo中定义管理器
class BookInfo(models.Model):
...
books = BookInfoManager()
c)使用方法
BookInfo.books.all()
2. 在管理器类中补充定义新的方法
a)打开 booktest / models.py 文件,定义方法 create
class BookInfoManager(models.Manager):
#创建模型类,接收参数为属性赋值
def create_book(self, title, pub_date):
#创建模型类对象self.model可以获得模型类
book = self.model()
book.btitle = title
book.bpub_date = pub_date
book.bread=0
book.bcommet=0
book.is_delete = False
# 将数据插入进数据表
book.save()
return book
b)为模型类 BookInfo 定义管理器 books 语法如下
class BookInfo(models.Model):
...
books = BookInfoManager()
c)调用语法如下:
book=BookInfo.books.create_book("abc",date(1980,1,1))
总结:
使用 Admin 站点
学习目标:
掌握 admin 管理站点的生成方式
Admin站点介绍
假设我们要设计一个新闻网站,我们需要编写展示给用户的页面,网页上展示的新闻信息是从哪里来的呢?是从数据库中查找到新闻的信息,然后把它展示在页面上。但是我们的网站上的新闻每天都要更新,这就意味着对数据库的增、删、改、查操作,那么我们需要每天写sql语句操作数据库吗? 如果这样的话,是不是非常繁琐,所以我们可以设计一个页面,通过对这个页面的操作来实现对新闻数据库的增删改查操作。那么问题来了,老板说我们需要在建立一个新网站,是不是还要设计一个页面来实现对新网站数据库的增删改查操作,但是这样的页面具有一个很大的重复性,那有没有一种方法能够让我们很快的生成管理数据库表的页面呢?有,那就是我们接下来要给大家讲的Django 的后台管理。Django 能够根据定义的模型类自动地生成管理页面。
使用 Django 的管理模块,需要按照如下步骤操作:
管理界面本地化
在 settings.py 中设置语言和时区
LANGUAGE_CODE = 'zh-hans' # 使用中国语言
TIME_ZONE = 'Asia/Shanghai' # 使用中国上海时间
创建超级管理员
创建管理员的命令如下,按提示输入用户名、邮箱、密码。
python manage.py createsuperuser
转存失败重新上传取消
打开浏览器,在地址栏中输入如下地址后回车。
http://127.0.0.1:8000/admin/
输入前面创建的用户名、密码完成登录。
转存失败重新上传取消
登录成功后界面如下,但是并没有我们自己应用模型的入口,接下来进行第三步操作。
转存失败重新上传取消
如果想要修改密码可以执行
python manage.py changepassword 用户名
App 应用配置
在每个应用目录中都包含了apps.py文件,用于保存该应用的相关信息。
在创建应用时,Django会向apps.py文件中写入一个该应用的配置类,如
from django.apps import AppConfig
class BooktestConfig(AppConfig):
name = 'booktest'
我们将此类添加到工程settings.py中的INSTALLED_APPS列表中,表明注册安装具备此配置属性的应用。
注册模型类
登录后台管理后,默认没有我们创建的应用中定义的模型类,需要在自己应用中的 admin.py 文件中注册,才可以在后台管理中看到,并进行增删改查操作。
打开 booktest / admin.py 文件,编写如下代码:
from django.contrib import admin
from booktest.models import BookInfo,HeroInfo
admin.site.register(BookInfo)
admin.site.register(HeroInfo)
到浏览器中刷新页面,可以看到模型类BookInfo和HeroInfo的管理了。
转存失败重新上传取消
点击类名称"BookInfo"(图书)可以进入列表页,默认只有一列。
转存失败重新上传取消
在列表页中点击"增加"可以进入增加页,Django会根据模型类的不同,生成不同的表单控件,按提示填写表单内容后点击"保存",完成数据创建,创建成功后返回列表页。
转存失败重新上传取消
在列表页中点击某行的第一列可以进入修改页。
转存失败重新上传取消
按照提示进行内容的修改,修改成功后进入列表页。在修改页点击“删除”可以删除一项。
转存失败重新上传取消
删除:在列表页勾选想要删除的复选框,可以删除多项。
转存失败重新上传取消
点击执行后进入确认页面,删除后回来列表页面。
转存失败重新上传取消
调整站点信息
Admin 站点的名称信息也是可以自定义的。
未调整前如下图:
转存失败重新上传取消
在 booktest / admin.py 文件中添加一下信息
from django.contrib import admin
admin.site.site_header = '传智书城'
admin.site.site_title = '传智书城MIS'
admin.site.index_title = '欢迎使用传智书城MIS'
刷新网站,效果如下
转存失败重新上传取消
总结:
调整列表页展示
学习目标:
能够调整列表页的展示效果
定义与使用 Admin 管理类
Django 提供的 Admin 站点的展示效果可以通过自定义 ModelAdmin 类来进行控制.
首先: 定义管理类需要继承自 admin.ModelAdmin 类,如下
# 导入
from django.contrib import admin
# 定义 admin 管理类
class BookInfoAdmin(admin.ModelAdmin):
pass
然后: 注册后才能使用, 注册有两种方式.
如下所示:
每列展示内容设置
使用方式:
# 使用方式:
list_display=[模型字段1, 模型字段2,...]
例如:
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
# 每列展示内容设置
list_display = ['id', 'btitle']
每页展示数量设置
使用方式:
# 使用方式:
list_per_page = 数量
例如:
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
# 每页展示数量设置
list_per_page = 2
在浏览器中查看区域信息的列表页面,效果如下图:
转存失败重新上传取消
"操作选项"的位置
使用方式:
顶部显示的属性,设置为 True 在顶部显示,设置为 False 不在顶部显示,默认为 True.
# 使用方式:
actions_on_top=True
底部显示的属性,设置为 True 在底部显示,设置为 False 不在底部显示,默认为 False.
# 使用方式:
actions_on_bottom=False
例如:
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
# "操作选项"的位置
actions_on_top = True
actions_on_bottom = True
在浏览器中刷新效果如下图:
转存失败重新上传取消
在浏览器中刷新效果如下图:
转存失败重新上传取消
点击列头可以进行升序或降序排列。
右侧过滤器栏
使用方式:
属性如下,只能接收字段,会将对应字段的值列出来,用于快速过滤。一般用于有重复值的字段。
# 使用方式:
list_filter=[]
例如:
打开 booktest / admin.py 文件,修改 HeroInfoAdmin 类如下:
class HeroInfoAdmin(admin.ModelAdmin):
# 右侧过滤器栏
list_filter = ['hbook', 'hgender']
在浏览器中刷新效果如下图:
转存失败重新上传取消
搜索框
使用方式:
属性如下,用于对指定字段的值进行搜索,支持模糊查询。列表类型,表示在这些字段上进行搜索。
# 使用方式:
search_fields=[]
例如:
打开 booktest / admin.py 文件,修改 HeroInfoAdmin 类如下:
class HeroInfoAdmin(admin.ModelAdmin):
# 搜索框
search_fields = ['hname']
在浏览器中刷新效果如下图:
转存失败重新上传取消
将方法作为列
列可以是模型字段,还可以是模型方法,要求方法有返回值。
通过设置 short_description 属性,可以设置在 admin 站点中显示的列名.
例如:
打开 booktest / models.py 文件,修改 BookInfo 类如下:
class BookInfo(models.Model):
...
# 增加新的函数
def haha(self):
return self.bpub_date.strftime('%Y年%m月%d日')
# 设置方法字段在 admin 中显示的标题
haha.short_description = '发布日期'
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
...
list_display = ['id','atitle','haha']
在浏览器中刷新效果如下图:
转存失败重新上传取消
方法列是不能排序的,如果需要排序需要为方法指定排序依据。
admin_order_field=模型类字段
打开 booktest / models.py 文件,修改 BookInfo 类如下:
class BookInfo(models.Model):
...
def haha(self):
return self.bpub_date.strftime('%Y年%m月%d日')
haha.short_description = '发布日期'
# 指定排序依据
haha.admin_order_field = 'bpub_date'
在浏览器中刷新效果如下图:
转存失败重新上传取消
关联对象
无法直接访问关联对象的属性或方法,可以在模型类中封装方法,访问关联对象的成员。
打开 booktest / models.py 文件,修改 HeroInfo 类如下:
class HeroInfo(models.Model):
...
def read(self):
return self.hbook.bread
read.short_description = '图书阅读量'
打开 booktest / admin.py 文件,修改 HeroInfoAdmin 类如下:
class HeroInfoAdmin(admin.ModelAdmin):
...
list_display = ['id', 'hname', 'hbook', 'read']
在浏览器中刷新效果如下图:
转存失败重新上传取消
总结:
学习目标:
掌握调整编辑页的各方法
属性如下:
fields=[]
点击某行 ID 的链接,可以转到修改页面,默认效果如下图:
转存失败重新上传取消
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
# 展示的字段写入 [] 中
fields = [
'btitle',
'bpub_date']
刷新浏览器效果如下图:
转存失败重新上传取消
属性如下:
fieldsets=(
('
组
1
标题
',{'fields':('
字段
1','
字段
2')}),
('
组
2
标题
',{'fields':('
字段
3','
字段
4')}),
)
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
...
# fields = ['btitle', 'bpub_date']
# 分组展示:
fieldsets = (
(
'基本', {
'fields': [
'btitle',
'bpub_date']}),
(
'高级', {
'fields'
: [
'bread',
'bcomment'],
'classes'
: (
'collapse',)
# 是否折叠显示
})
)
刷新浏览器效果如下图:
转存失败重新上传取消
说明:fields 与 fieldsets 两者选一使用.
在 一对多 的关系中,可以在 一端 的编辑页面中编辑 多端 的对象
嵌入多端对象的方式包括表格、块两种.
可以用块的形式嵌入:
打开 booktest / admin.py 文件,创建 HeroInfoStackInline 类.
class HeroInfoStackInline(admin.StackedInline):
model = HeroInfo
# 要编辑的对象
extra =
1# 附加编辑的数量
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
...
inlines = [HeroInfoStackInline]
刷新浏览器效果如下图:
转存失败重新上传取消
可以用表格的形式嵌入:
打开 booktest / admin.py 文件,创建 HeroInfoTabularInline 类.
class HeroInfoTabularInline(admin.TabularInline):
model = HeroInfo
extra =
1
打开 booktest / admin.py 文件,修改 BookInfoAdmin 类如下:
class BookInfoAdmin(admin.ModelAdmin):
...
inlines = [HeroInfoTabularInline]
刷新浏览器效果如下图:
转存失败重新上传取消
上传图片
学习目标:
掌握如何上传图片
准备工作
Django 有提供文件系统支持,在 Admin 站点中可以轻松上传图片。
使用 Admin 站点保存图片,需要安装 Python 的图片操作包
pip install Pillow
配置
默认情况下,Django 会将上传的图片保存在本地服务器上,需要配置保存的路径。
我们可以将上传的文件保存在静态文件目录中,如我们之前设置的 static_files 目录中在 settings.py 文件中添加如下上传保存目录信息
# 图片保存的根目录
MEDIA_ROOT=os.path.join(BASE_DIR,"static_files")
为模型类添加 ImageField 字段
我们为之前的 BookInfo 模型类添加一个 ImageFiled
class BookInfo(models.Model):
...
image = models.ImageField(upload_to='booktest',
verbose_name='图片',
null=True)
upload_to 选项指明该字段的图片保存在 MEDIA_ROOT 目录中的哪个子目录
进行数据库迁移操作
# 生成迁移文件
python manage.py makemigrations
# 进行数据迁移
python manage.py migrate
使用 Admin 站点上传图片
进入 Admin 站点的图书管理页面,选择一个图书,能发现多出来一个上传图片的字段
转存失败重新上传取消
选择一张图片并保存后,图片会被保存在 static_files / booktest/ 目录下。
在数据库中,我们能看到 image 字段被设置为图片的路径
转存失败重新上传取消
总结:
欢迎学习 Redis 课程
Redis 是一个高性能的 key-value 数据库。
学习目标
Redis 介绍
学习目标
nosql 介绍
NoSQL:一类新出现的数据库( not only sql )
NoSQL 和 SQL 数据库的比较:
Redis 简介
Redis 特性
Redis 优势
Redis 应用场景
推荐阅读
总结:
Redis 安装
学习目标:
掌握 redis 的安装方法
安装步骤:
wget http://download.redis.io/releases/redis-x.x.x.tar.gz
转存失败重新上传取消
tar xzf redis-x.x.x.tar.gz
sudo mv ./redis-x.x.x /usr/local/redis/
cd /usr/local/redis/
sudo make
转存失败重新上传取消
sudo make test
转存失败重新上传取消
sudo make install
cd /usr/local/bin
ls -all
转存失败重新上传取消
sudo cp /usr/local/redis/redis.conf /etc/redis/
其他补充
https://brew.sh/
https://www.cnblogs.com/cloudshadow/p/mac_brew_install_redis.html
总结:
redis 配置
学习目标
能够根据参考资料修改常用 Redis 配置
配置
sudo vim /etc/redis/redis.conf
核心配置选项
bind 127.0.0.1
port 6379
daemonize yes
dbfilename dump.rdb
dir /var/lib/redis
logfile "/var/log/redis/redis-server.log"
database 16
slaveof
参考资料
redis 配置信息http://blog.csdn.net/ljphilp/article/details/52934933
总结:
redis 中的服务器端和客户端
学习目标
了解 Redis 服务器端和客户端的命令
服务器端
ps aux | grep redis 查看 redis 服务器进程
sudo kill -9 pid 杀死 redis 服务器
sudo redis-server /etc/redis/redis.conf 指定加载的配置文件
客户端
转存失败重新上传取消
ping
转存失败重新上传取消
select 10
转存失败重新上传取消
总结:
Redis 的数据类型
学习目标
能够知道 redis 中常见的数据类型
数据结构
注意:键不能重复
转存失败重新上传取消
数据操作行为
点击中⽂官⽹查看命令⽂档 http://redis.cn/commands.html
重要文档
总结:
string 操作
学习目标:
掌握 string 类型对应的方法
string 类型简介:
添加或修改
如果设置的键不存在则为添加,如果设置的键已经存在则修改
set key value
set name itcast
转存失败重新上传取消
setex key seconds value
setex aa 3 aa
转存失败重新上传取消
mset key1 value1 key2 value2 ...
mset a1 python a2 java a3 c
转存失败重新上传取消
append key value
append a1 haha
转存失败重新上传取消
获取
get key
get name
mget key1 key2 ...
mget a1 a2 a3
转存失败重新上传取消
删除
详⻅下节键的操作,删除键时会将值删除
总结:
Redis 中和键有关的命令
学习目标:
能够知道删键的相关命令
键命令
查找键,参数⽀持正则表达式
keys *
转存失败重新上传取消
keys a*
转存失败重新上传取消
exists key
exists a1
转存失败重新上传取消
type key
type a1
转存失败重新上传取消
del key1 key2 ...
del a2 a3
转存失败重新上传取消
expire key seconds
expire a1 3
转存失败重新上传取消
ttl key
ttl bb
转存失败重新上传取消
总结:
学习目标
掌握 Redis 中 hash 类型数据的增删改查相关命令
hset key field value
user
的属性 name
为 itheima
hset user name itheima
hmset key field1 value1 field2 value2 ...
u2
的属性 name
为 itcast
、属性 age
为 11
hmset u2 name itcast age 11
转存失败重新上传取消
hkeys key
hkeys u2
转存失败重新上传取消
hget key field
u2
属性name
的值hget u2 name
转存失败重新上传取消
hmget key field1 field2 ...
u2
属性 name
、 age
的值hmget u2 name age
转存失败重新上传取消
hvals key
u2
所有属性的值hvals u2
转存失败重新上传取消
hdel key field1 field2 ...
u2
的属性 age
hdel u2 age
转存失败重新上传取消
补充:
可能出现的错误
转存失败重新上传取消
MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.
Redis被配置为保存数据库快照,但它目前不能持久化到硬盘。用来修改集合数据的命令不能用
list 的相关操作
学习目标
能够说出 Redis 中 list 操作数据的方法
list 类型
增加
lpush key value1 value2 ...
lpush a1 a b c
转存失败重新上传取消
转存失败重新上传取消
rpush key value1 value2 ...
rpush a1 0 1
转存失败重新上传取消
转存失败重新上传取消
linsert key before或after 现有元素 新元素
linsert a1 before b 3
转存失败重新上传取消
获取
lrange key start stop
lrange a1 0 -1
转存失败重新上传取消
修改索引位置的值
lset key index value
lset a1 1 z
转存失败重新上传取消
删除
lrem key count value
lpush a2 a b a b a b
转存失败重新上传取消
lrem a2 -2 b
lrange a2 0 -1
转存失败重新上传取消
截取
ltrim key start stop
总结:
Set 集合类型
学习目标:
掌握 set 类型的操作方法
set 集合特点:
增加
sadd key member1 member2 ...
sadd a3 zhangsan sili wangwu
转存失败重新上传取消
获取
smembers key
smembers a3
转存失败重新上传取消
删除
srem key
srem a3 wangwu
转存失败重新上传取消
总结:
zset 类型
学习目标:
掌握 zset 类型的操作方法
zset 类型特点
增加
zadd key score1 member1 score2 member2 ...
zadd a4 4 lisi 5 wangwu 6 zhaoliu 3 zhangsan
获取
zrange key start stop
zrange a4 0 -1
转存失败重新上传取消
zrangebyscore key min max
zrangebyscore a4 5 6
转存失败重新上传取消
zscore key member
zscore a4 zhangsan
转存失败重新上传取消
删除
zrem key member1 member2 ...
zrem a4 zhangsan
转存失败重新上传取消
zremrangebyscore key min max
zremrangebyscore a4 5 6
转存失败重新上传取消
总结:
Python 和 redis 的交互
学习目标:
掌握 redis 与 python 的交互方式
安装包
安装 Redis 的有3种方式https://github.com/andymccurdy/redis-py
pip install redis
easy_install redis
一步步执行:
wget https://github.com/andymccurdy/redis-py/archive/master.zip
unzip master.zip
cd redis-py-master
sudo python setup.py install
调⽤模块
引⼊模块
# 引⼊模块
from redis import StrictRedis
这个模块中提供了 StrictRedis 对象,⽤于连接 redis 服务器
并按照不同类型提供 了不同⽅法,进⾏交互操作
准备
在桌面上创建 redis 目录
使用 pycharm 打开 redis 目录
创建 redis_string.py 文件
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
except Exception as e:
print(e)
string-增加
⽅法 set,添加键、值,如果添加成功则返回 True,如果添加失败则返回 False
编写代码如下:
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
# 添加键 name,值为 itheima
result = sr.set('name','黑马')
#输出响应结果,如果添加成功则返回 True,否则返回 False
print(result)
except Exception as e:
print(e)
string-获取
⽅法 get,添加键对应的值,如果键存在则返回对应的值,如果键不存在则返回 None
编写代码如下:
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
# 获取键 name 的值
result = sr.get('name')
# 输出键的值,如果键不存在则返回 None
print(result)
except Exception as e:
print(e)
string-修改
⽅法 set,如果键已经存在则进⾏修改,如果键不存在则进⾏添加
编写代码如下:
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
# 设置键 name 的值,如果键已经存在则进⾏修改,如果键不存在则进⾏添加
result = sr.set('name', '传智')
# 输出响应结果,如果操作成功则返回 True,否则返回 False
print(result)
except Exception as e:
print(e)
string-删除
⽅法 delete,删除键及对应的值,如果删除成功则返回受影响的键数,否则则返回 0
编写代码如下:
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
# 设置键 name 的值,如果键已经存在则进⾏修改,如果键不存在则进⾏添加
result = sr.delete('name')
# 输出响应结果,如果删除成功则返回受影响的键数,否则则返回 0
print(result)
except Exception as e:
print(e)
获取键
⽅法 keys,根据正则表达式获取键
编写代码如下
# 引⼊模块
from redis import StrictRedis
if __name__=="__main__":
try:
# 创建 StrictRedis 对象,与 redis 服务器建⽴连接
sr = StrictRedis()
# 获取所有的键
result = sr.keys()
# 输出响应结果,所有的键构成⼀个列表,如果没有键则返回 []
print(result)
except Exception as e:
print(e)
总结:
学习目标:
掌握 StrictRedis 对象的相关方法
# 创建对象
sr = StrictRedis( host=
'localhost', port=
6379, db=
0)
# 简写
sr=StrictRedis()
根据不同的类型,拥有不同的实例⽅法可以调⽤
与前⾯学的 redis 命令对应,⽅法需要的参数与命令的参数⼀致
string
keys
hash
list
set
zset
学习目标
能够根据课件中的步骤搭建 Redis 的主从
转存失败重新上传取消
配置主
ifconfig
转存失败重新上传取消
/etc/redis/redis.conf
文件cd /etc/redis/
sudo vi redis.conf
bind 172.16.238.128
sudo service redis stop
sudo redis-server redis.conf
配置从
/etc/redis/redis.conf
文件在 /etc/redis/ 目录下复制:
sudo cp redis.conf ./slave.conf
redis/slave.conf
文件sudo vi slave.conf
bind 172.16.238.128
port 6378
slaveof 172.16.238.128 6379
sudo redis-server slave.conf
redis-cli -h 172.16.238.128 info Replication
转存失败重新上传取消
redis-cli -h 172.16.238.128 -p 6379
redis-cli -h 172.16.238.128 -p 6378
set aa aa
转存失败重新上传取消
get aa
集群
学习目标:
了解集群的概念
为什么要有集群
集群的概念
当请求到来首先由负载均衡服务器处理,把请求转发到另外的一台服务器上。
redis 集群
转存失败重新上传取消
转存失败重新上传取消
搭建集群
参考阅读
总结:
集群中机器的配置
学习目标:
掌握集群中机器的配置方法
port
7003bind
172.16.238.128daemonize yes
pidfile
7003.pid
cluster-enabled yes
cluster-config-file
7003_node.conf
cluster-node-timeout
15000appendonly yes
port
7004bind
172.16.238.128daemonize yes
pidfile
7004.pid
cluster-enabled yes
cluster-config-file
7004_node.conf
cluster-node-timeout
15000appendonly yes
port
7005bind
172.16.238.128daemonize yes
pidfile
7005.pid
cluster-enabled yes
cluster-config-file
7005_node.conf
cluster-node-timeout
15000appendonly yes
总结:三个⽂件的配置区别在 port、pidfile、cluster-config-file 三项
redis-server
3.conf
redis-server
4.conf
redis-server
5.conf
总结:
创建集群
学习目标:
掌握创建集群的方法
创建集群
sudo apt-get install ruby
转存失败重新上传取消
redis-trib.rb create --replicas 1 172.16.238.128:7000 172.16.238.128:7001 172.16.238.128:7002 172.16.238.128:7003 172.16.238.128:7004 172.16.238.128:7005
数据验证
redis-cli -h 172.16.238.128 -c -p 7002
set name itheima
服务器写数据的判断
CRC16
总结:
Python 交互
学习目标:
能够使用集群与 python 进行交互
pip install redis-py-cluster
from rediscluster import StrictRedisCluster
if __name__ == '__main__':
try:
# 构建所有的节点,Redis会使⽤CRC16算法,将键和值写到某个节点上
startup_nodes = [
{'host': '172.16.238.128', 'port': '7000'},
{'host': '172.16.238.128', 'port': '7003'},
{'host': '172.16.238.128', 'port': '7001'},
]
# 构建StrictRedisCluster对象
src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
# 设置键为name、值为itheima的数据
result=src.set('name','itheima')
print(result)
# 获取键为name
name = src.get('name')
print(name)
except Exception as e:
print(e)
总结:
Git 引入
学习目标:
知道我们引入 git 的目的
以及能够知道 git 可以使用的场景
场景
如果遇到文本需要修改很多次, 并且都需要做备份和记录的时候怎么办呢?
我们可以使用 git
它能够帮助我们记录各个不同的版本. 并且可以实时的把各个不同的版本进行整合记录.
转存失败重新上传取消
总结:
Git 简介
学习目标:
知道 git 的定义以及大概流程
定义
Git 是目前世界上最先进的分布式版本控制系统(没有之一)
源代码管理的目的
Git 的诞生历史( 了解 )
转存失败重新上传取消
git 开发时间表
Git 迅速成为最流行的分布式版本控制系统,尤其是 2008 年,GitHub 网站上线了,它为开源项目免费提供 Git 存储,无数开源项目开始迁移至 GitHub,包括 jQuery,PHP,Ruby 等等
Git 管理源代码特点
转存失败重新上传取消
转存失败重新上传取消
Git 操作流程图解
Git服务器 --> 本地仓库 --> 客户端 --> 本地仓库 --> Git服务器
转存失败重新上传取消
总结:
Git 中的模块
学习目标:
掌握 git 中的三个区域以及各自的特点
工作区
git 中的工作区指的就是我们平时写代码的区域,
例如:
编译器中( pycharm, vscode ).
作用:
工作区的主要作用就是对文件进行 添加、修改、删除等操作
暂存区
git 中临时存储数据的一个区域, 我们成为暂存区.
特点:
这个区域我们一般看不到. 但他实际存在. 我们可以把代码临时保存在这里. 也可以撤销
主要作用是:
为了让用户能够把数据进行长久存储前, 可以进行筛查, 反悔等操作, 而创建的区域
仓库区
git 中本地进行长久存储的一个区域
特点:
主要存储一个小阶段的成果. 防止丢失
我们一般把暂存区的内容存储到这里. 以方便以后查看.
暂存区的内容存储到本地仓库区后, 暂存区的内容将会销毁.
我们可以在本地仓库区存放多个版本的信息. 并且可以在不同的版本中进行跳转.
提示:本地仓库是个 .git 隐藏文件
关联关系
上面三个区的关系, 我们可以通过如下的图片查看:
转存失败重新上传取消
总结:
学习目标:
知道 git 的安装和配置
安装 git
# 安装 git
sudo apt-get install git
# 密码:chuanzhi
参数解读:
sudo : 超级管理员权限, 如果使用该权限, 需要添加密码
apt-get : 包管理工具
install : 安装的意思
转存失败重新上传取消
想要查看 git 是否安装成功, 需要我们调用 git 命令:
git
调用该命令后, 如果出现大篇幅的命令, 代表安装 git 成功.
如果出现 'git 不是内部或外部命令' 字样. 则 git 安装失败
在桌面创建 test
文件夹, 作为项目文件
mkdir Desktop/
test
进入到刚刚创建的文件中 : cd Desktop/test/
初始化 git , 从而创建本地仓库
# 初始化 git 得到本地仓库
git init
补充:
进入到 test
,并创建本地仓库 .git
新创建的本地仓库.git
是个空仓库
转存失败重新上传取消
创建本地仓库.git
后
转存失败重新上传取消
# 配置个人的用户名:
git config user.name
'张三'
# 配置个人的邮箱地址:
git config user.email
'[email protected]'
转存失败重新上传取消
配置个人信息后
转存失败重新上传取消
默认不配置的话,会使用全局配置里面的用户名和邮箱 全局 git 配置文件路径:~/.gitconfig
sudo apt-get install git
学习目标:
能够掌握 git 的相关常见操作
test
里面创建 login.py
文件,用于版本控制演示转存失败重新上传取消
#
使用方式
:
git status
敲这个命令后:
转存失败重新上传取消
# 使用方式:
# 第一种提交方式:
git add .
# 第二种提交方式:
git add login.py
转存失败重新上传取消
# 使用方式:
git commit -m
'描述信息'
转存失败重新上传取消
# 提交到暂存区:
git add .
# 提交到本地仓库区:
git commit -m
"版本描述"
add
和 commit
操作转存失败重新上传取消
# 使用方式:
# 第一种:
git log
# 第二种:
git reflog
转存失败重新上传取消
git reflog 可以查看所有分支的所有操作记录(包括 commit 和 reset 的操作),包括已经被删除的commit 记录,git log 则不能察看已经删除了的 commit 记录
学习目标:
掌握 git 版本回退和代码撤销的方法
方案一:
# 使用方式:
git reset --hard
版本
HEAD
表示当前最新版本HEAD^
表示当前最新版本的前一个版本HEAD^^
表示当前最新版本的前两个版本,以此类推...HEAD~1
表示当前最新版本的前一个版本HEAD~10
表示当前最新版本的前10个版本,以此类推...例如:
git reset --hard HEAD^
转存失败重新上传取消
转存失败重新上传取消
方案二:
当版本非常多时可选择的方案
通过每个版本的版本号回退到指定版本
git reset --hard
版本号
转存失败重新上传取消
转存失败重新上传取消
# 使用方式:
git checkout
文件名
例如:
新加代码 num3 = 30
,不 add
到暂存区,保留在工作区
git checkout
文件名
转存失败重新上传取消
转存失败重新上传取消
新加代码 num3 = 30
,并 add
到暂存区
# 第一步:将暂存区代码撤销到工作区
git reset HEAD
文件名
# 第二步:撤销工作区代码
git checkout
文件名
转存失败重新上传取消
git reset --hard
版本
/
版本号
git checkout
文件名
git reset HEAD
文件名
和 git checkout
文件名
Git 远程仓库
学习目标:
掌握远端仓库的创建和克隆方式
准备工作:
在 Github 网站上创建远程仓库
创建远程仓库
提示:
Github 网站作为远程代码仓库时的操作和本地代码仓库一样的.
只是仓库位置不同而已!
转存失败重新上传取消
编辑仓库信息
转存失败重新上传取消
查看远端仓库
转存失败重新上传取消
将远程仓库拷贝到本地
远程仓库地址 https://github.com/zhangxiaochuZXC/test007.git
转存失败重新上传取消
总结:
使用 SSH 克隆项目
学习目标:
掌握 SSH 克隆项目的配置和方法
了解 SSH 登录方式
我们之前已经可以通过 https 的方式, 从 Github 获取远端仓库了:
git clone https://地址
除此以外, 我们还可以使用 SSH 的方式从 Github 上获取远端仓库.
如果想要使用该功能, 我们需要把 SSH 的公钥添加到 Github 上.
那么就要把这台电脑的 SSH 公钥添加到这个 Github 账户上
在 Github 上配置 SSH 公钥
转存失败重新上传取消
转存失败重新上传取消
修改电脑端 git 配置
在电脑上配置 Github 的注册邮箱和用户名
# 在命令行调用如下命令:
vim .gitconfig
# 修改下列字段:
[user]
email = 邮箱@163.com
name = 注册的 github 名称
转存失败重新上传取消
生成 SSH 公钥
# 调用该命令, 生成 SSH 公钥
ssh-keygen -t rsa -C "[email protected]"
转存失败重新上传取消
查看生成的公钥信息:
# 使用该命令查看公钥文件:
cat ~/.ssh/id_rsa.pub
完善 Github 中 SSH 公钥信息
转存失败重新上传取消转存失败重新上传取消
补充:删除旧的秘钥
删除~/.ssh目录,这里存储了旧的密钥
rm -r .ssh
使用 SSH 克隆远端项目到本地
复制 Github 中 SSH 的对应地址, 使用 git clone 的命令克隆到本地:
# 使用方法:
git clone [email protected]:hjokerkevin/kevin.git
总结:
学习目标:
掌握如何给不同的用户克隆同一个项目
立项:克隆远程仓库+配置身份信息+创建项目+推送项目到远程仓库
克隆远程仓库的命令
# 克隆远端的项目到本地
# 可以使用 HTTPS
cd Desktop/manager/
git clone https://github.com/zhangxiaochuZXC/test007.git
# 也使用 SSH
cd Desktop/manager/
git clone [email protected]:Fly744055970/test002.git
克隆远程仓库到本地
转存失败重新上传取消
克隆成功后查看经理的文件
转存失败重新上传取消
配置经理身份信息
# 进入经理的工程中
cd Desktop/manager/test007/
# 配置经理的身份信息
git config user.name
'经理'
git config user.email
'[email protected]'
转存失败重新上传取消
获取项目:克隆项目到本地、配置身份信息
克隆项目到本地
# 进入张三的文件夹中
cd Desktop/zhangsan/
# 克隆远端的项目到本地
git clone https://github.com/zhangxiaochuZXC/test007.git
转存失败重新上传取消
克隆成功后查看张三的文件
转存失败重新上传取消
配置张三身份信息
# 进入张三的工程中
cd Desktop/zhangsan/test007/
# 配置张三的身份信息
git config user.name
'张三'
git config user.email
'[email protected]'
张三身份信息配置成功后即可跟经理协同开发同一个项目
经理在工程中增加了新的文件, 并在其中添加了代码
转存失败重新上传取消
推送项目到远程仓库
# 工作区添加到暂存区
git add .
# 暂存区提交到仓库区
git commit -m
'立项'
# 推送到远程仓库
git push
转存失败重新上传取消
转存失败重新上传取消
git cnfig --
glbal credential.helper cache
git cnfig credential.helper
'cache --timeut=3600'git cnfig --
glbal credential.helper stre
在以后的项目开发过程中,Pycharm 可以自动记住密码
经理已经修改了远端的工程, 所以张三可以拉取远端最新的工程到本地
# 调用该命令可以拉取远端工程:
git pull
多人协同开发
学习目标:
掌握多人协同开发的方法
修改张三的代码并推送到远端
git add .
git commit -m '第一个变量'
转存失败重新上传取消
转存失败重新上传取消
转存失败重新上传取消
经理拉取远端代码到本地
经理想要获得张三提供的内容, 需要调用拉取的命令:
# 拉取远端代码到本地:
git pull
修改经理的代码并推送到远端
进入经理本地仓库: cd Desktop/manager/test007/
编辑代码: num2 = 20
本地仓库记录版本:
git add .
git commit -m '第二个变量'
推送到远程仓库:git push
转存失败重新上传取消
转存失败重新上传取消
转存失败重新上传取消.
转存失败重新上传取消
张三拉取远端代码到本地
本次可以把 num2 同步到张三的本地仓库
转存失败重新上传取消
按照以上步骤循环操作,即可实现基本的协同开发
总结:
学习目标:
掌握冲突产生的原因和解决方法
设想一下:
如果张三和经理都修改了同一行代码, 并且都进行了提交, 那么服务端应该保存谁的代码呢?
这时就会产生冲突
张三先编辑文件中的代码
cd Desktop/zhangsan/test007
git pull
num3 = 30
git add .
git commit -m '
第三个变量
'
git push
转存失败重新上传取消
转存失败重新上传取消
经理后编辑文件中的代码
cd Desktop/manager/test007/
num3 = 300
git add .
git commit -m '
第三个变量
'
git push
转存失败重新上传取消
转存失败重新上传取消
转存失败重新上传取消
add
、commit
、push
转存失败重新上传取消
转存失败重新上传取消
pull
没有影响,就算真正解决了冲突代码补充:
pull
在修改,修改完立即commit
和push
标签
学习目标:
知道标签的作用和设置方法
标签的作用
当某一个大版本完成之后,需要打一个标签
作用:
转存失败重新上传取消
模拟设置标签
例如:
# 标签名为 v1.0
# 标签描述为: version 1.0
git tag -a v1.0 -m 'version 1.0'
转存失败重新上传取消
例如:
# 将标签推送到远端:
git push origin v1.0
这里的 origin 代表远端的意思
转存失败重新上传取消
转存失败重新上传取消
补充:删除本地和远程标签
# 删除本地标签
git tag -d 标签名
# 删除远程仓库标签
git push origin --delete tag 标签名
总结:
Vue.js 入门,介绍 Vue.js 里面的一些通用概念和用法。
Vue.js 是前端三大新框架:Angular.js、 React.js、 Vue.js 之一,Vue.js 目前的使用和关注程度在三大框架中稍微胜出,并且它的热度还在递增。
Vue.js 可以作为一个 js 库来使用,也可以用它全套的工具来构建系统界面,这些可以根据项目的需要灵活选择,所以说,Vue.js 是一套构建用户界面的渐进式框架。
Vue 的核心库只关注视图层,Vue 的目标是通过尽可能简单的 API 实现响应的数据绑定,在这一点上 Vue.js 类似于后台的模板语言。
Vue 也可以将界面拆分成一个个的组件,通过组件来构建界面,然后用自动化工具来生成单页面( SPA - single page application ) 系统。
转存失败重新上传取消
vue 作者: 尤玉溪
毕业于上海复旦附中, 在美国完成大学学业, 现任职于纽约 Google Creative Lab。
前后研发了 Clear 开源软件和 Vue.js 框架.
2016年9月3日,在南京的 JSConf 上,Vue 作者尤雨溪正式宣布加盟阿里巴巴 Weex 团队,尤雨溪称他将以技术顾问的身份加入 Weex 团队来做 Vue 和 Weex 的 JavaScript runtime 整合,目标是让大家能用 Vue 的语法跨三端
Vue.js 读音 /vjuː/, 类似于 view
Vue.js 是一个轻巧、高性能、可组件化的 MVVM 库,同时拥有非常容易上手的 API
转存失败重新上传取消
Vue.js 是一个构建数据驱动的 Web 界面的库
Vue.js 是一套构建用户界面的 渐进式框架
转存失败重新上传取消
通俗的说:
Vue.js 使用文档已经写的很完备和详细了
通过以下地址可以查看: https://cn.vuejs.org/v2/guide/
vue.js 如果当成一个库来使用
可以通过下面地址下载: https://cn.vuejs.org/v2/guide/installation.html
学习目标:
介绍 Vue 的基本使用步骤
第一步:导包
官方提供了两个包
开发包:
vue.js
生产包:
vue.min.js
<script src="./js/vue.js">script>
第二步: 创建 Vue 对象
window.onload =
function (){
// 创建一个 vue 对象
var
vm =
newVue({
el:
'#box',
data: {
}
});
}
第三步: 创建一个容器
创建一个容器和上面的对象关联.
<div id="box">
div>
<head>
<meta charset="UTF-8">
<title>
Vue
的基本使用
title>
<script src="./js/vue.js">script>
<script>
window.onload = function () {
// 02: 创建 vue 对象
var vm = new Vue({
// 绑定操作对象
el:'#box',
data: {
content: 'Vue的基本使用'
}
});
}
script>
head>
<body>
<div id="box">
{{content}}
div>
body>
html>
学习目标
学会操作数据, 修改属性, 调用方法
{{
变量名
}}
示例
<head>
<meta charset="UTF-8">
<title>
操作数据
title>
<script src="./js/vue.js">script>
<script>
window.onload = function () {
// 创建 vue 对象
//var是定义局部变量,不写是定义全局变量
var vm = new Vue({
el:'#box',
data:{
name:'张三'
}
});
}
script>
head>
<body>
<div id="box">
{{name}}
<p>
{{name}}
p>
div>
body>
html>
<标签 v-bind:属性="属性值">标签>
示例
<head>
<meta charset="UTF-8">
<title>
02-
操作数据
title>
<script src="./js/vue.js">script>
<script>
window.onload = function () {
// vue 对象
var vm = new Vue({
el:'#box',
data:{
url:'http://www.baidu.com'
}
});
}
script>
head>
<body>
<div id="box">
<a href="http://www.baidu.com">
百度
a>
<a v-bind:href="url">
百度
a>
<a :href="url">
百度
a>
div>
body>
html>
<标签 v-on:事件名="调用的函数名">标签>
示例
<head>
<meta charset="UTF-8">
<title>
操作数据
title>
<script src="./js/vue.js">script>
<script>
window.onload = function () {
// uve对象
var vm = new Vue({
el:'#box',
data:{
count: 1
},
// 在这里定义方法:
methods: {
fnAddClick:function () {
this.count += 1
}
}
});
}
script>
head>
<body>
<div id="box">
{{count}}
<button v-on:click='fnAddClick'>
按钮
button>
<button @click='fnAddClick'>
按钮
button>
div>
body>
html>
条件渲染
学习目标:
掌握 v-if, v-else-if, v-else, v-show 的使用
条件指令
通过条件指令可以控制元素的创建(显示)或者销毁(隐藏)
window.onload = function () {
var vm = new Vue({
el:'#box',
data:{
isOk:true,
isTrue:true,
}
});
}
第一个p标签 第一个p标签 第二个p标签 第一个p标签 第二个p标签 V-SHOW