Python-Django基本笔记

Django 框架
1.WEB 与 服务器
1.WEB : 表示用户可以浏览的网页内容(HTML,CSS,JS)
2.服务器
专门给用户提供服务的一台机器
1.硬件与软件
硬件范畴:一台机器
软件范畴:一个能够接受用户请求并给出响应的程序
1.APACHE
2.TOMCAT
3.IIS(Internet Information Service)
4.Nginx
2.服务器的作用
1.存储WEB上所需要的信息(HTML,图片,js,css,音视频)
2.处理用户的请求(request)并给出响应(response)
3.执行服务器端的程序 : 查找数据库
3.服务器 与 WEB之间的关系
WEB需要放在服务器上才能够被用户访问
2.框架
1.什么是框架
框架是一个为了解决开放性问题而存在的一种结构.框架本身会提供一些最基本的功能.我们只需要在基本功能之上搭建属于自己的操作即可.
2.PYTHON WEB 框架
1.Django : 重量级的WEB框架
2.Tornado : 异步框架
3.Flask : 轻量级框架
3.Django 框架
1.什么是Django
是一个开源框架,2005年发布,采用Python语言编写的.早期是做新闻和内容管理的网站的.Django本身提供了强大的后台管理系统.
2.Django的框架模式 - MTV
M : Models 层
模型层,负责数据库建模以及CRUD的操作
T : Templates 层
模板层,处理用户显示的内容的,比如:html
V : Views 层
视图层,处理与用户交互的部分内容

	MVC : 三层架构
		M:Models,模型层,与数据库打交道
		V:Views,视图层,处理用户显示的内容的
		C:Controller,控制器层,处理与用户交互的部分内容
	MTV            MVC
	M    ....      M
	T    ....      V
	V    ....      C
3.Django的官方介绍
	官网:http://www.djangoproject.com
	中文文档:http://djangobook.py3k.cn/2.0/

4.Django 框架的使用
1.安装Django框架
1.查看已安装的Django版本
1.进入到终端以及python交互模式
python3 / ipython3
2.交互模式中 输入 import django
如果未报错:当前环境下已经安装好Django
如果报错:当前环境未安装过Django
3.查看已安装的版本
交互模式中:django.VERSION
2.安装
1.在线安装 - 使用 pip / pip3
sudo pip3 install django
(安装Django的最新版本)

			sudo pip3 install django==1.11.8
			(安装Django的指定版本)
		2.离线安装
			1.下载Django包
			2.在环境下解压Django包
				tar -xvf Django-1.11.8.tar.gz
			3.进入到目录中,找到 setup.py 文件
				sudo python3 setup.py install
2.使用Django
	1.创建目录
		用于保存所有的Django项目
		mkdir Django

		使用 django-admin 指令创建Django项目
		语法:django-admin startproject 项目名
	2.启动服务,访问网站
		在项目中找到 manage.py
		通过manage.py启动项目(服务)
		python3 manage.py runserver
	3.访问网站
		启动服务之后,浏览器访问
		http://localhost:8000
		http://127.0.0.1:8000
3.Django 项目结构介绍
	1.manage.py
		负责执行Django中的各项操作
		如:
			启动服务:runserver
			创建应用:startapp
			... ...
	2.主目录(目录名称与项目名称一致)
		1.__init__.py
			项目的初始化文件,服务被启动时,该文件自动被执行
		2.urls.py
			项目的基础url配置文件(路由配置文件)
		3.wsgi.py
			应用服务器配置文件
		4.settings.py
			项目的配置文件
			1.BASE_DIR:获取当前项目的绝对路径
			2.DEBUG : 调试模式
				开发过程:推荐使用 True
				上线运行:必须改为 False
			3.ALLOWD_HOSTS
				设置允许访问本项目的地址列表
				如果为空,只有本机能访问(localhost/127.0.0.1)
				推荐写 ['*'],任何表示该机器的地址都可以访问当前项目

				如果允许被其他机器访问的话,启动服务时,必须使用以下方式:
					./manage.py runserver 0.0.0.0:端口号
			4.INSTALLED_APPS
				指定已安装的应用,如果有自定义应用的话,需要在此注册
			5.MIDDLEWARE
				注册中间件
			6.ROOT_URLCONF
				指定项目的基础路由配置文件
			7.TEMPLATES
				指定模板的信息
			8.DATABASES
				指定数据库的信息
			9.LANGUAGE_CODE
				语言设置,如果需要中文的话,允许将值更改为 "zh-Hans"

			10.TIME_ZONE
				指定时区,建议修改为 "Asia/Shanghai"
4.URL的使用
	1.urls.py
		默认在主目录中,主路由配置文件,包含所有的地址映射
	2.测试
		1.在主目录中,创建 views.py
			作用:包含所有定义好的视图(处理程序)

	3.url 函数
		作用:为了匹配用户的访问路径
		语法:
			url(regex,views,kwargs=None,name=None)		
				1.regex:允许是正则表达式,匹配请求的url的
				2.views:对应的视图处理函数
				3.kwargs:字典,用来向views传参的,如果没有参数的话则可以省略
				4.name:字符串类型,为url起别名,在地址反向查询时使用
	4.通过url向视图传参
		http://localhost:8000/run/15
		http://localhost:8000/run/26
		http://localhost:8000/run/78
		1.使用正则表达式传参
			使用子组传参,一个子组是一个参数,要传递多个参数的话使用多个子组
			子组 - ()

			urlpatterns = [
				# 访问路径是run/的时候,交给run_views去处理
				url(r'^run/$',run_views),
				# 访问路径是run/两位数字的时候,交给run1_views去处理
				url(r'^run/(\d{2})/$',run1_views),
				# 访问路径是run/四位数字/两位数字的时候,交给run2_views去处理
				url(r'^run/(\d{4})/(\d{2})/$',run2_views),


			]
			注意:
					1.url()中,一个子组表示一个参数
					2.在views中,对应的处理函数要根据url()中子组的个数,相应的定义参数.定义的参数要位于request之后

=====================================================
1.url()
1.注意
如果一个访问路径能够匹配到多个url()的时候,那么只找匹配的第一个url()去执行
2.url 传参
1.通过正则的子组传参
2.使用 url()第三个参数 - 字典传参
dic = {
‘name’:‘sa.zh’,
‘age’:‘25’
}
url(r’^show/$’,show_views,dic)

		views.py
		def show_views(request,name,age):
			pass

2.Django 中的 应用
1.什么是应用
应用就是网站中一个独立的模块程序
在Django中,主目录一般不处理用户的具体请求,主目录主要做的是项目的初始化以及请求的分发.而具体的请求由各个应用去处理
2.创建应用
1.指令
./manage.py startapp 应用名称
ex:
./manage.py startapp news
2.在 settings.py 中进行注册
在 INSTALLED_APPS 中追加应用名称
INSTALLED_APPS = [
‘django.contrib.admin’,
… …,
‘自定义应用名称’
]
3.练习
1.创建新项目 - netease
2.创建 index 应用,并注册
3.创建 sport 应用,并注册
4.创建 music 应用,并注册
5.创建 news 应用,并注册
3.应用的结构组成
1.migrations 目录
存放的是数据库的中间文件
2.init.py
应用的初始化文件
3.admin.py
应用的后台管理配置文件
4.app.py
应用的属性配置文件
5.models.py
Models 与模型相关的配置文件
6.tests.py
测试模块
7.views.py
定义视图的文件
4.分布式路由系统
# 交给 music 应用去处理(转交给music的urls)
from django.conf.urls import include
# url(r’^music/’,include(‘music.urls’)),
http://localhost:8000/music/****
# 交给 music 应用中的 index_views 视图去处理
http://localhost:8000/music/index
# 交给 sport 应用去处理(转交给sport的urls)
http://localhost:8000/sport/****

	练习:
		1.访问路径 localhost:8000/news/index
			转交给 news 的urls 再找到index_views处理
		2.访问路径 localhost:8000/sport/index
			转交给 sport 的urls 再找到index_views处理
		3.访问路径 localhost:8000/index/index
			转交给 index 的urls 再找到index_views处理

	需求:
		1.访问路径 http://localhost:8000/music/
			交给 music 应用中的 index_views 视图去处理
			url(r'^$',index_views)
		2.访问路径 http://localhost:8000/music/show
			交给 music 应用中的 show_views 视图去处理


		 http://localhost:8000/music/index
		 	交给 music 应用中的 index_views 视图去处理

		news 应用:
		1. http://localhost:8000/news/
			交给 news 应用中的 index_views 视图去处理

		需求
			1.http://localhost:8000/
				交给 index 应用中的 index_views 视图去处理
			2.http://localhost:8000/login
				交给 index 应用中的 login_views 视图去处理
			3.http://localhost:8000/register
				交给 index 应用中的 register_views 视图去处理

			只要访问路径不是 music , news , sport 的话,一律都交给 index 应用去处理

3.Django 中的 模板(Templates)
1.什么是模板
模板就是要动态呈现给用户的网页内容
模板的本质就是网页 - 前后端结合的网页
2.模板的设置
在 settings.py中, TEMPLATES 变量

	1.BACKEND : 指定模板的搜索引擎
	2.DIRS : 指定模板的存放目录们
		如果DIRS中为空的话,那么Django会自动的到每个应用中搜索一个叫 templates 的目录作为模板存放目录
	3.APP_DIRS
		True : 优先从DIRS指定的目录中查找模板,如果没找到的话,再搜索应用中的templates目录
3.模板的加载方式
	1.使用 loader 获取模板,通过HttpResponse进行响应
		from django.template import loader

		def index_views(request):
			#1.通过loader加载模板
			t = loader.get_template("模板名称")
			#2.将模板渲染成字符串
			html = t.render()
			#3.通过HttpResponse响应给客户端
			return HttpResponse(html)

	2.使用render直接加载并返回模板
		def index_views(request):
			return render(request,'模板名称')
4.模板的语法
	1.变量
		1.作用:允许将后端的数据传递给模板在模板中进行显示
		2.Django中允许作为变量传递给模板的数据类型
			字符串,数字,列表,元组,字典,函数,对象
		3.变量的语法
			变量们必须要封装到字典中才能传递给模板
			1.使用 loader 加载模板
				dic = {
					'变量1':'值1',
					'变量2':'值2',
					... ...
				}

				t=loader.get_template('模板名称')
				# 渲染成字符串时需要传递变量字典到模板中
				return HttpResponse(t.render(dic))
			2.使用render加载并返回模板
				dic = {
					'变量1':'值1',
					'变量2':'值2',
				}

				return render(request,'模板名称',dic)
		4.在模板中使用变量
			{{变量名}}
	2.标签
		1.作用
			将服务器端的功能嵌入到模板中
		2.语法
			{% 标签内容 %}
	3.标签详解
		1.comment 标签
			{% comment %}

			{% endcomment %}
			作用:在服务器端就被注释的内容,不会被渲染到客户端的

		2.for 标签
			作用:循环遍历 列表,字典,元组
			语法:
				{% for 变量 in 列表|字典|数组 %}
				{% endfor %}

				循环中允许使用 forloop 内置变量来获取循环相关的信息
					forloop.counter : 记录当前循环的次数(从1开始计算)
					forloop.first : 判断是否为第一次遍历
					forloop.last : 判断是否为最后一次遍历
		3.if标签
			1.if
				{% if 条件 %}
					条件满足时要执行的内容
				{% endif %}
			2.if ... else
				{% if 条件 %}
					满足条件时执行的内容
				{% else %}
					不满足条件时执行的内容
				{% endif %}
			3.if...elif...else
				{% if 条件1 %}
					满足条件1执行的内容
				{% elif 条件2 %}
					或满足条件2执行的内容
				{% elif 条件3 %}
					或满足条件3执行的内容
				{% else %}
					或都不满足时执行的内容
				{% endif %}

{
‘dog’: <index.views.Dog object at 0x7fdcac316048>,
‘l’: [‘金毛狮王’, ‘白眉鹰王’, ‘青翼斧王’],
‘dic’: {‘HLM’: ‘红楼梦’, ‘SHZ’: ‘水浒传’, ‘XYJ’: ‘西游记’},
‘f’: 88,
‘request’: <WSGIRequest: GET ‘/03_var/’>,
‘t’: (‘潘金莲’, ‘西门庆’, ‘武大郎’)
}

==================================================================1.模板
1.过滤器
在显示变量数据之前,对数据进行过滤筛选
2.过滤器的语法
{{变量|过滤器}}
3.常用过滤器
1.{{value|upper}}
将value变为大写
2.{{value|lower}}
将value变为小写
3.{{value|add:num}}
将num累加到value后
4.{{value|floatformat:n}}
将value四舍五入到n位小数
5.{{value|truncatechars:n}}
将value截取保留至n位字符(包含…)
4.静态文件
1.什么是静态文件
在Django中,不被解释器动态解析的文件就称为静态文件
如:图片,js,css,静态的html
在Django中,物理路径是无法找到静态文件的
2.Django中静态文件的处理
需要在 settings.py中设置有关静态文件的信息:
1.设置静态文件的访问路径
STATIC_URL=’/static/’
ex:
http://localhost:8000/static/xxx
2.设置静态文件的存储路径
STATICFILES_DIRS=(os.path.join(BASE_DIR,‘静态文件目录名’))

					STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'))
				静态文件目录存放位置:
					1.所有应用中创建一个 同名目录
					2.项目的根目录处也可以创建一个 同名目录

			3.访问静态文件
				1.直接使用 静态文件访问路径 进行访问
					http://localhost:8000/static/...
					<img src="/static/...">
						<img src="/static/images/admin.png">
						<img src="http://localhost:8000/static/images/admin.png">
				2.使用 {% static %} 访问静态资源
					{% static %} 表示的就是静态资源的访问路径
					1.在模板的最顶层增加
						{% load static %}
					2.在使用静态资源时
						<img src="{% static 'images/list_filter.png'%}">
				练习:
					1.创建一个项目 - fruitday
					2.创建一个应用 - index 
					3.配置主路由 和 应用路由
					4.在index中配置首页的 url 和 模板
						url : /
						模板 : index.html(配置好所有的静态文件)
							静态文件:图片,css
5.模板的继承
	1.语法
		1.在父模板中
			必须要标识出哪些内容在子模板中是允许被修改的
			标签:
				{% block 名称 %}
					父模板中的内容
				{% endblock %}
			block的作用:
				1.在父模板中是正常显示的
				2.在子模板中,如果不修改block中的内容的话则按照父模板中的内容进行显示.要是修改了的话,则按照子模板中的内容显示了.
		2.在子模板中
			1.指定继承自哪个模板
				{% extends '父模板名称' %}
			2.增加block标签,改写属于自己的内容
							{% block 名称 %}
							{% endblock %}
6.url() 的name参数
	1.url的语法:
		url(regex,views,kwargs,name)
			name : 为了给当前的url 或 地址起别名 反向解析时用.
			反向解析:通过 name 的值来匹配出对应的 regex(地址)

		url(regex,views,kwargs=None,name='别名')
	2.在模板中通过 别名 找地址
		{% url '别名' %}

		带参数的别名
			{% url '别名' 参数1 参数2 ...%}

	3.在视图中实现name别名的反向解析

		1.基本解析
			url=reverse('别名')
			url就是通过别名所解析出来的地址

=============================================================
1.模型 - Models
1.什么是模型
模型,是根据数据库中数据表的结构来创建出来的class.每一张表对应到编程语言中就是一个class.表中的每一个列,到编程语言中就是class中的一个属性.
2.创建 和 使用模型 - ORM
1.什么是ORM
ORM : Object Relational Mapping
简称:ORM,O/RM,O/R Mapping
中文:对象关系映射

		三大特征:
			1.数据表 到 类(class)的映射
				允许将数据表(Table) 自动生成一个 类(Class)
				允许将类(Class) 自动生成一个 数据表(Table)
			2.数据类型的映射
				允许将表中字段的数据类型 自动 映射成编程语言中对应的数据类型
				允许将编程语言中的数据类型 自动 映射成表中字段对应的数据类型
			3.关系映射
				允许将表与表之间的关系 自动 映射成类与类之间的关系
				允许将类与类之间的关系 自动 映射成表与表之间的关系
	2.ORM的优点
		1.提高了开发效率,能够自动完成表与类之间的映射
		2.可以省略庞大的数据访问层.即便不用SQL编码,也能完成对数据库的CRUD操作
	3.创建 和 配置 数据库
		1.创建数据库(支持中文)
			create database 数据库名 default charset utf8 collate utf8_general_ci;
		2.Django中数据库的配置
			在 settings.py中配置数据库的信息
			DATABASES = {
				'default':{
					'ENGINE':'...',
					'NAME':'....',
				}
			}
			连接MySQL数据库的配置:
				1.ENGINE : 连接到数据库的引擎(驱动程序)
					django.db.backends.mysql
				2.NAME : 数据库名
				3.USER : 用户名称,通常为 root
				4.PASSWORD : 密码, 学校为 123456
				5.HOST : 要连接的主机
					本机:localhost 或 127.0.0.1
				6.PORT : 指定端口号 
					MYSQL:3306
			注意:
				Django 中要连接MySQL数据库的话依赖于 MySQLdb
				通过 pymysql 解决该问题
					sudo pip3 install pymysql==0.7.11
				在项目的主目录中的 __int__.py :
					import pymysql
					pymysql.install_as_MySQLdb()
	4.数据库的同步操作
		1. ./manage.py makemigrations
			作用:将每个应用下的 models.py 文件生成一个数据库的中间文件,并将中间文件保存在 migrations 的目录中
		2. ./manage.py migrate
			作用:将每个应用下的migrations目录中的中间文件同步到数据库中
3.编写Models(重难点)
	1.注意
		1.Models中的每个class都称为 模型类(Model) 或 实体类(Entry)
			实体:表示的就是数据库中表中的一条记录
			实体完整性:约束表中的记录不完全重复
		2.Models中的每个类都必须继承自 models.Model
	2.举个例子
		在 index 应用中 的 models.py 中
		from django.db import models
		# 创建 Publisher 实体类
		# 表示 出版社 的信息,属性如下:
		# 1.name : 出版社的名称(varchar,string)
		# 2.address : 出版社的地址
		# 3.city : 出版社所在城市
		# 4.country : 出版社所在国家
		# 5.website : 出版社的网址
		class Publisher(models.Model):
			# 1.name : 出版社的名称(varchar,string)
			name = models.CharField(max_length=30)
			# 2.address : 出版社的地址(字符串,长度50)
			address = models.CharField(max_length=50)
			# 3.city : 出版社所在城市(字符串,长度20)
			city = models.CharField(max_length=20)
			# 4.country : 出版社所在国家(字符串,长度20)
			country = models.CharField(max_length=20)
			# 5.website : 出版社的网址
			website = models.URLField()
	3.Django 中的 Models 的语法
		语法:
			class ClassName(models.Model):
				属性 = models.字段类型(字段选项)

			字段类型:映射到数据库表中的数据类型
				CharField - varchar
			字段选项:对生成的字段的说明信息
				max_length=30

		字段类型(Field Types)
			1.BooleanField()
			2.CharField()
			3.DateField()
			4.DateTimeField()
			5.DecimalField()
				money=models.DecimalField(max_digits=7,decimal_places=2)
			6.EmailField()
				# 存电子邮件地址 - varchar
			7.FloatField()
			8.ImageField()
				# 存图片路径 - varchar
				uimg=models.ImageField(upload_to='images/users/')
			9.IntegerField()
			10.URLField()
				# 存网址 - varchar
			11.TextField()
				# 存大量数据 - text	
		字段选项(Field Options)
			1.default
				为当前属性(字段)指定默认值
			2.null
				指定当前属性(字段)的值是否允许为空,默认为False,表示不能为空
			3.db_column
				指定当前属性(字段)对应到数据库的列名,如果不指定则采用属性名作为列名
		练习:
			1.在 models.py 中追加2个class
				1. Author - 作者
					1.name - 姓名
					2.age - 年龄
					3.email - 邮箱(允许为空)
				2. Book - 图书
					1.title - 书名
					2.publicate_date - 出版时间
			2.生成日志文件,再同步回数据库
4.相关指令
	1.数据的版本切换
		1. ./manage.py migrate
			执行所有应用中最新版本的数据库中间文件
		2. ./manage.py migrate 应用名称 版本号
			./manage.py migrate index 0003
	2.通过数据库自动导出models
		./manage.py inspectdb > 文件名.py

2.模型中的 CRUD
1.通过 ORM 向 数据库中 增加数据
1. Entry.objects.create(属性=值,属性=值)
返回值:创建好的实体
2.创建一个 Models 对象,并通过 save() 完成增加
obj = Entry(属性=值,属性=值)
obj.save()
3.使用字典构建对象,并调用其 save() 完成增加
dic = {
‘属性1’:‘值1’,
‘属性2’:‘值2’,
}

		obj = Entry(**dic)
		obj.save()
	练习:
		使用三种方式,分别向 index_book,index_publisher 中各增加三条数据
2.查询数据 (重难点)
	通过 Entry.objects 调用查询接口
	1.基本查询操作
		语法:all()
		用法:Entry.objects.all()
		返回:QuerySet(查询结果集,是一个封装了若干对象的列表)
	2.查询指定列的操作
		语法:values('列1','列2',...)
		用法:Entry.objects.values('列1','列2')
		返回:QuerySet
		注意:values()可以用在所有查询返回QuerySet的方法的后面

		Author.objects.values('name','age')
		Author.objects.all().values('name','age')

	3.查询指定列的操作
		语法:values_list()
		用法:Entry.objects.values_list()
		返回:QuerySet,是一个由若干元组所组成的列表
	4.对查询数据进行排序
		语法:order_by()
		用法:Entry.objects.order_by('列1','-列2')
			默认是升序排序,列名前加 "-",则表示该列按降序排序
	5.对条件取反
		语法:exclude()
		用法:Entry.objects.exclude(条件)
		1.
			Author.objects.exclude(id=3)
			select * from index_author where not (id=3)
		2. 
			Author.objects.exclude(id=3,age=85)
			select * from index_author where not (id=3 and age=85)


作业:
	从 AUthor 中取出所有的数据,并显示在 模板中(table)
		姓名    年龄    邮箱               操作
		老舍    85     [email protected]     删除 修改
		老舍    85     [email protected]     删除 修改
		巴金    75     [email protected]      删除 修改
		冰心    95     [email protected]    删除 修改

money decimal(7,2)

Navicate

class A(object):
name = None
age = None

class B(object):
a = A()

b = B()
print(b.a.name)

一个老师可以带多门课
每门课只能由一个老师来讲

all():

<QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>, <Author: Author object>]>

[
<Author: Author object>,
<Author: Author object>,
<Author: Author object>,
<Author: Author object>
]

<QuerySet [<Author: 老舍>, <Author: 老舍>, <Author: 巴金>, <Author: 冰心>]>

[
<Author: 老舍>,
<Author: 老舍>,
<Author: 巴金>,
<Author: 冰心>
]

老舍 85 [email protected]
老舍 85 [email protected]
巴金 75 [email protected]
冰心 96 [email protected]

values():
<QuerySet [{‘age’: 85, ‘name’: ‘老舍’}, {‘age’: 85, ‘name’: ‘老舍’}, {‘age’: 75, ‘name’: ‘巴金’}, {‘age’: 96, ‘name’: ‘冰心’}]>

[
{‘age’: 85, ‘name’: ‘老舍’},
{‘age’: 85, ‘name’: ‘老舍’},
{‘age’: 75, ‘name’: ‘巴金’},
{‘age’: 96, ‘name’: ‘冰心’}
]

values_list():
<QuerySet [(‘老舍’, 85), (‘老舍’, 85), (‘巴金’, 75), (‘冰心’, 96)]>

[
(‘老舍’, 85),
(‘老舍’, 85),
(‘巴金’, 75),
(‘冰心’, 96)
]

order_by():
<QuerySet [<Author: 冰心>, <Author: 老舍>, <Author: 老舍>, <Author: 巴金>]>

[
<Author: 冰心>,
<Author: 老舍>,
<Author: 老舍>,
<Author: 巴金>
]

===========================================================

1.Models - 模型
1.查询
1.只查询一条数据
语法:get(条件)
用法:Entry.objects.get(条件)
注意:
适用于只能查询一条数据时使用
查询多于一条结果或没查询出结果时都会抛异常
2.根据条件查询部分行数据(重难点)
语法:filter(条件)
用法:Entry.objects.filter(条件)
1.使用 Entry 中的属性作为查询条件
如果有多个查询条件的话,使用 , 隔开,映射到sql语句中,一律使用 and 进行关联
ex:
1.Author.objects.filter(id=1)
select * from index_author where id=1
2.Author.objects.filter(id=1,name=‘老舍’)
select * from index_author where id=1 and name=‘老舍’
2.使用 Field Lookups(查询谓词) 完成复杂条件查询
查询谓词:每一个独立的查询谓词就是一个独立的查询条件
所有支持使用查询条件的位置处,都允许使用 查询谓词
filter(),get(),exclude()
Entry.objects.filter(属性__查询谓词=值)
练习:
在 Author 实体中,查询所有 email 中包含字符 ‘a’ 的Author的信息
2.修改
1.修改单个数据
1.查
通过 get() 得到要修改的实体对象
2.改
通过实体对象的属性修改值
3.保存
通过实体对象的save()保存回数据库
练习:
1.将id为1的Author的name属性值修改为 舒庆春

			au = Author.objects.get(id=1)
			au.name = "舒庆春"
			au.save()
	2.批量修改数据
		调用查询结果集的update(属性=值,属性=值)实现批量修改
		将 age=85的author的信息的email更改为 [email protected]

		Author.objects.filter(age=85).update(email='[email protected]')
3.删除
	调用实体对象/查询结果集的 delete() 可以完成删除

	1.删除单个对象
		au = Author.objects.get(id=1)
		au.delete()
	2.删除多个对象
		auList = Author.objects.filter(age__gte=58)
		auList.delete()

	练习:
		1.Author实体中增加一个列 , isActive (BooleanField) , 默认值为 True
		2.删除 : 将对应 author 的isActive更改为False
		3.查询 : 只查询出 isActive 为True的信息,其余的不查询
4.转发 & 重定向
	1.转发
		将请求转交给其他的视图去处理
		表现:地址栏不会发生改变
		原因:只有一次请求,所以地址栏上就是最初请求的地址
	2.重定向
		重新向新的地址发送请求
		语法:
			HttpResponseRedirect('重定向地址'')
			redirect('重定向地址')
		表现:地址栏会现实最后一次请求的地址
		原因:重定向导致浏览器向服务器发送了两次请求
5.F查询 和 Q查询
	1.F()
		作用:用于在执行中获取某列的值
		语法:
			from django.db.models import F
			F('列名')

			Author.objects.all().update(age=F('age')+10)
	2.Q()
		作用:在查询条件中完成或(or)的操作
		语法:
			from django.db.models import Q
			Q(条件1)|Q(条件2)
		#查询id为1 或 年龄大于100岁的人的信息
		Author.objects.filter(Q(id=1)|Q(age__gt=100))

2.使用后台管理Models
1.创建后台管理员
./manage.py createsuperuser
Username : 输入用户名,默认为 tarena
Email Address : 输入电子邮件地址
Password:输入密码
Password(again):确认密码
2.基本管理
1.在应用中的 admin.py 中注册要管理的Models
1.admin.py
作用:注册要管理的Models,只有在此注册Models才允许被管理
2.注册 Models
from .models import *
from django.contrib import admin

			admin.site.register(Entry)
	2.修改 models.py 去处理显示的内容
		1.在models.py中的各个class 追加 
			def __str__(self):
				return self.name
		2.为各个class中的属性增加字段说明
			verbose_name='显示名称'
			ex
				name=models.CharField(max_length=30,verbose_name='姓名')
		3.为各个class追加内部类 Meta
			class Entry(models.Model):
				... ...
				... ...

				class Meta:
					1.db_table
						指定该实体对应到表的名称,取值为字符串
						该操作必须先同步回数据库
					2.verbose_name
						指定该实体类在admin中显示的名字(单数)
						取值为 字符串
					3.verbose_name_plural
						指定该实体类在admin中显示的名字(复数)
						verbose_name_plural = verbose_name
					4.ordering
						指定实体信息们在列表页的排序规则
						取值是一个列表,默认按升序排序,降序的话使用 "-"
3.高级管理
	1. 在 admin.py 中创建高级管理类
		1.定义高级管理类 - EntryAdmin
			必须继承自 admin.ModelAdmin
			ex:
				class AuthorAdmin(admin.ModelAdmin):
					pass
		2.注册高级管理类
			admin.site.register(Entry,EntryAdmin)

	2.允许在EntryAdmin中增加的管理属性
		1.list_display
			作用:指定在 列表页 中能够显示的字段们
			取值:由属性名组成的元组或列表
		2.list_display_links
			作用:定义在列表页中也能够链接到详情页的字段们
			取值:同上
			注意:取值必须出现在 list_display 中
		3.list_editable
			作用:指定在列表页中就允许被修改的字段们
			取值:同上
			注意:取值必须出现在 list_display中但不能出现在 list_display_links 中
		4.search_fields
			作用:指定允许被搜索的字段们
			取值:同上
		5.list_filter
			作用:在列表页的右侧增加一个过滤器,允许实现快速筛选
			取值:同上
		6.date_hierarchy
			作用:在列表页的顶部增加一个时间选择器
			取值:取值必须是DateField 或 DateTimeField
		7.fields
			作用:在详情页面上,要显示哪些字段并按照什么样的顺序显示
		8.fieldsets
			作用:在详情页面中对字段们进行分组显示
			注意:fieldsets 与 fields 是不能共存的
			取值:
				fieldsets = (
					#分组1
					(
						"分组名称",{
							'fields':('属性1','属性2'),
						}
					),
					#分组2
					()
				)
		作业:
			为 Publisher 增加管理功能
			1.基本功能
				1.指定每个列所显示的名称
				2.指定表名为 publisher
				3.指定每个实体对象在列表页中所显示的中文名
			2.高级功能
				1.在列表页中显示name,address,city属性值
				2.address 和 city 是可编辑的
				3.右侧显示过滤器,允许按照 city 和 country 进行筛选
				4.分组显示
					name,address,city 为基本选项
					country,website为高级选项,并可折叠

Author.objects.filter(id=1,name=‘老舍’)
<QuerySet [<Author: Author object>]>

Author.objects.filter(name=‘莫言’)
<QuerySet []>

Author.objects.filter(email__contanins=‘a’)
<QuerySet [<Author: Author object>, <Author: Author object>, <Author: Author object>]>

update index_author set age = age + 10

================================================================
1.关系映射
1.一对一映射
1.什么是一对一
A表中的一条记录只能与B表中的一条记录相关联
B表中的一条记录也只能与A表中的一条记录相关联

		典型代表:一夫一妻制

		在数据库中的实现:
			A表:设置 主键
			B表:增加一列,引用自A表的主键(外键),并且增加唯一约束
	2.语法
		在关联的两个类的任何一个类中,增加对另外一个类的引用
		属性 = models.OneToOneField(Entry)
		ex:
			class Wife(models.Model):
				name = models.CharFiled(...)
				age = models.IntegerField(...)
				author = models.OneToOneField(Author)
	3.查询
		class Wife(models.Model):
			name = models.CharFiled(...)
			age = models.IntegerField(...)
			author = models.OneToOneField(Author)

		正向查询:通过 wife 找 author
			# 获取id为1的wife的信息
			wife = Wife.objects.get(id=1)
			# 再获取wife所关联的author
			author = wife.author
		反向查询:通过 author 找 wife
			Django 会通过 OneToOneField() 在关联的实体类中增加一个隐式属性,表示对当前实体的引用
			隐式属性名成为 :当前类名的全小写形式

			# 先获取id为2的author的信息
			author=Author.objects.get(id=2)
			# 再获取author对应的wife
			wife = author.wife
2.一对多映射
	1.什么是一对多
		A表中的一条数据可以与B表中的任意多条数据相关联
		B表中的一条数据只能与A表中的一条数据相关联

		商品类型 与 商品之间的关系
		出版社(Publisher) 与 图书(Book)
	2.在数据库中的体现
		通过外键(Foreign Key) 来实现一对多
		在"多"表中增加外键(Foreign Key)对"一"表中的主键进行引用
	3.语法
		通过外键(Foreign Key)
		在"多"实体中,增加:
			属性 = models.ForeignKey(Entry)
	4.查询
		Book(多) 和 Publisher(一)

		class Book(models.Model):
			... ...
			publisher = models.ForeignKey(Publisher)
		正向查询 : 通过 Book 查询 Publisher
			book=Book.objects.get(id=1)
			publisher=book.publisher
		反向查询 : 通过 Publisher 查询 Book
			Django会通过ForeignKey()向关联的类中增加一个隐式属性 : 当前类_set
3.多对多映射
	1.什么是多对多
		A表中的一条记录可以与B表中的任意多条记录相匹配
		B表中的一条记录可以与A表中的任意多条记录相匹配
	2.在数据库中的体现
		必须创建第三张表,关联涉及到的两张表的数据
	3.语法
		在涉及到的两个类的任意一个类中,都可以增加对另外一个类的多对多的引用
			entry=models.ManyToManyField(Entry)
		ex:
			创建书籍和作者之间的多对多的引用
				可以在书籍实体中,增加多作者的引用
				可以在作者实体中,增加对书籍的引用
				以上方式 二选一
			class Book(models.Model):
				title = models.CharField(xxx)
				publicate_date = models.DateField()
				author = models.ManyToManyField(Author)
	4.查询
		class Book(models.Model):
			title = models.CharField(xxx)
			publicate_date = models.DateField()
			author = models.ManyToManyField(Author)

		正向查询:通过Book找到对应的所有的Author
			# 查询id为1的书籍的信息
			book=Book.objects.get(id=1)
			# 查询book对应的所有的作者
			authors=book.author.all()

			通过关联属性查询对应的所有信息
		方向查询:通过Author查询所有的Book
			Django会通过ManyToManyField()在关联类中增加一个隐式属性
			属性名:当前类_set
			# 查询id为2的Author的信息
			author = Author.objects.get(id=2)
			# 查询author对应的所有的书籍
			books=author.book_set.all()
	练习:
		创建 Author 与 Publisher 多对多关系
			1.查询 老舍 所签约的所有出版社
			2.查询 北京大学出版社 下所有的签约作者

2.HTTP 通信协议
1.什么是HTTP
HTTP:Hyper Text Transfer Protocol
超级 文本 传输 协议

	作用:规范了数据是如何打包以及传递的
2.请求消息
	由 请求起始行,请求消息头,请求主体

	请求主体:
		post和put两种提交方式会产生请求主体
3.响应消息
	由 响应起始行,响应消息头,响应主体

3.HttpRequest

select a.name,b.title from book as b
inner join book_author as ba
on b.id=ba.book_id
inner join author as a
on a.id=ba.author_id;

-> select a.name,p.name 
-> from author as a
-> inner join author_publisher as ap
-> on a.id = ap.author_id
-> inner join publisher as p
-> on p.id = ap.publisher_id
-> where a.name='老舍'
-> ;

==============================================================
1.HttpRequest
1.HttpRequest介绍
HttpRequest,在Django中是对请求对象的封装体现.会封装请求过程中所有的信息.在Django中,HttpRequest被封装成了request被自动传到了视图处理函数中.
2.HttpRequest 中的主要内容
1.request.scheme : 请求协议
2.request.body : 请求主体
3.request.path : 请求路径(资源具体路径)
4.request.get_host() : 请求的主机地址 / 域名
5.request.method : 获取请求方法
6.request.GET : 封装了GET请求方式提交的数据
7.request.POST : 封装了POST请求方式提交的数据
8.request.COOKIES : 封装了cookie的数据
9.request.META : 封装了请求的元数据
request.META.HTTP_REFERER : 封装了请求的源地址

3.获取请求提交的数据
	1.get 请求方式
		request.GET['名称']

	  1.使用表单提交数据
	    <form></form>
	  2.通过超链接拼查询字符串
	  	<a href="地址?参数1=值1&参数2=值2"></a>
	  	此种方式,属于http标准


		Django中,通过url传递参数
		 url(r'^01_test/(\d+)',test_views)
		 此种方式,非http标准的,属于Django标准


	2.post 请求方式
		request.POST['名称']

		CSRF:Cross-Site Request Forgery
			跨站点伪装攻击

			解决方案:
				1.取消 CSRF 的验证
					删除 settings.py 中 MIDDLEWARE 中 CsrfViewMiddleware 中间件
				2.开放验证权限,无须验证,直接进入
					在视图处理函数之上增加一个装饰器
					@csrf_protect
				3.必须要通过验证后才可以请求
					在模板中<form>下的第一行增加:
					{% csrf_token %}
4.Django中的表单处理
	表单页面的get 和 post 请求,是由同一个视图(views)去处理的

2.使用forms模块处理表单
1.forms模块的作用
通过forms模块,允许将表单与class相结合,允许通过class生成表单
2.使用 forms 模块
1.创建 forms.py 文件
2.导入 forms
from django import forms
3.创建class,一个class对应成一个表单
class LoginForm(forms.Form):
pass
4.在class中创建属性
一个属性对应着一个表单控件
(参考文档)
3.在 模板中,解析 form 对象
1.注意
1.需要自定义
2.需要自定义按钮
2.处理方法
在视图中创建 forms.Form 的对象,并发送到模板中
ex:
form = RemarkForm()
return render(request,‘xx.html’,locals())
1.手动解析
在模板中:
{% for field in form %}
{{field}} : 表示的就是控件
{{field.label}} : 表示的就是控件前的文本
{% endfor %}
2.自动解析
1.{{form.as_p}}
将form对象中的每个属性使用p标记包裹起来,再显示在网页上
2.{{form.as_ul}}
将form对象中的每个属性使用li标记包裹起来,再显示在网页上
注意:必须手动提供


      3.{{form.as_table}}
      将form对象中的每个属性使用tr标记包裹起来
      注意:必须手动提供

      练习:
      	1.创建一个数据库 - day07
      	2.在程序中创建一个 Models - Users
      		uname - 用户名
      		upwd - 密码
      		uage - 年龄
      		uemail - 邮箱
      	  同步回数据库,并通过后台管理的方式插入几条测试数据
      	3.创建 forms.Form 类,表示登录的 form 
      		需要 用户名,密码  两个控件(俩属性)
      	4.将 form 放在模板中,解析成对应的控件
      		自己提供<form>以及提交按钮
      	5.点击提交按钮时,要验证用户名和密码的值是否正确
      
      4.在视图中,通过forms.Form自动获取表单数据
      	1.通过 forms.Form 的构造,接收post数据
      		form = XXXForm(request.POST)
      	2.需要让 form 通过验证后,再取值
      		form.is_valid()
      			返回True:提交的数据已经通过验证,允许接收表单提交的数据
      			返回False:提交的数据验证未通过,无法取值
      	3.获取表单中的数据
      		通过 form.cleaned_data (字典) 接收提交的数据
      
      	作业:
      		1.创建 RegisterForm,根据 Users 的属性,构建 RegisterForm 的属性
      		2.在模板中,根据RegisterForm,创建表单控件
      		3.提交数据时,再交给RegisterForm接收提交的数据,通过验证后,将数据插入到数据库中
      

      form.cleaned_data:
      {‘uname’: ‘zhangsanfeng’, ‘upwd’: ‘yinsusu’}
      request.POST:
      <QueryDict:
      {
      ‘csrfmiddlewaretoken’: [‘3qC1M0ZSlEFFD8R8OuT2LImdzOL2EMtUrBpFDLzrXs4jLT5FNQZQFZ0ZTsUWkSc0’],
      ‘uname’: [‘zhangsanfeng’],
      ‘upwd’: [‘yinsusu’]
      }>

      http://localhost:8000/04_get/?uname=sanfeng.zhang&upwd=yinsusu

      <QueryDict: {‘upwd’: [‘123456’], ‘uname’: [‘sanfeng.zhang’]}>

      [‘COOKIES’, ‘FILES’, ‘GET’, ‘META’, ‘POST’, ‘class’, ‘delattr’, ‘dict’, ‘dir’, ‘doc’, ‘eq’, ‘format’, ‘ge’, ‘getattribute’, ‘gt’, ‘hash’, ‘init’, ‘iter’, ‘le’, ‘lt’, ‘module’, ‘ne’, ‘new’, ‘reduce’, ‘reduce_ex’, ‘repr’, ‘setattr’, ‘sizeof’, ‘str’, ‘subclasshook’, ‘weakref’, ‘_encoding’, ‘_get_post’, ‘_get_raw_host’, ‘_get_scheme’, ‘_initialize_handlers’, ‘_load_post_and_files’, ‘_mark_post_parse_error’, ‘_messages’, ‘_post_parse_error’, ‘_read_started’, ‘_set_post’, ‘_stream’, ‘_upload_handlers’, ‘body’, ‘build_absolute_uri’, ‘close’, ‘content_params’, ‘content_type’, ‘csrf_processing_done’, ‘encoding’, ‘environ’, ‘get_full_path’, ‘get_host’, ‘get_port’, ‘get_raw_uri’, ‘get_signed_cookie’, ‘is_ajax’, ‘is_secure’, ‘method’, ‘parse_file_upload’, ‘path’, ‘path_info’, ‘read’, ‘readline’, ‘readlines’, ‘resolver_match’, ‘scheme’, ‘session’, ‘upload_handlers’, ‘user’, ‘xreadlines’]

      {‘DESKTOP_SESSION’: ‘ubuntu’, ‘XMODIFIERS’: ‘@im=fcitx’, ‘SERVER_NAME’: ‘localhost’, ‘QT_LINUX_ACCESSIBILITY_ALWAYS_ON’: ‘1’, ‘XDG_CONFIG_DIRS’: ‘/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg’, ‘XDG_GREETER_DATA_DIR’: ‘/var/lib/lightdm-data/tarena’, ‘CONTENT_LENGTH’: ‘’, ‘LANGUAGE’: ‘zh_CN:zh’, ‘QUERY_STRING’: ‘’, ‘PATH_INFO’: ‘/02_meta/’, ‘wsgi.errors’: <io.TextIOWrapper name=’’ mode=‘w’ encoding=‘UTF-8’>, ‘VIRTUALENVWRAPPER_PYTHON’: ‘/usr/bin/python3’, ‘INSTANCE’: ‘’, ‘VIRTUALENVWRAPPER_WORKON_CD’: ‘1’, ‘PWD’: ‘/home/tarena/Django/Day07’, ‘SERVER_PORT’: ‘8000’, ‘GPG_AGENT_INFO’: ‘/home/tarena/.gnupg/S.gpg-agent:0:1’, ‘GNOME_DESKTOP_SESSION_ID’: ‘this-is-deprecated’, ‘IM_CONFIG_PHASE’: ‘1’, ‘CLUTTER_IM_MODULE’: ‘xim’, ‘CONTENT_TYPE’: ‘text/plain’, ‘XDG_SEAT’: ‘seat0’, ‘GNOME_KEYRING_CONTROL’: ‘’, ‘wsgi.url_scheme’: ‘http’, ‘UPSTART_JOB’: ‘unity7’, ‘QT_IM_MODULE’: ‘fcitx’, ‘UPSTART_EVENTS’: ‘xsession started’, ‘QT4_IM_MODULE’: ‘fcitx’, ‘COMPIZ_BIN_PATH’: ‘/usr/bin/’, ‘REMOTE_ADDR’: ‘127.0.0.1’, ‘wsgi.file_wrapper’: <class ‘wsgiref.util.FileWrapper’>, ‘JOB’: ‘unity-settings-daemon’, ‘HTTP_UPGRADE_INSECURE_REQUESTS’: ‘1’, ‘SSH_AUTH_SOCK’: ‘/run/user/1000/keyring/ssh’, ‘LOGNAME’: ‘tarena’, ‘GTK_MODULES’: ‘gail:atk-bridge:unity-gtk-module’, ‘COMPIZ_CONFIG_PROFILE’: ‘ubuntu’, ‘wsgi.run_once’: False, ‘HTTP_ACCEPT_LANGUAGE’: ‘en-GB,en;q=0.5’, ‘wsgi.multiprocess’: False, ‘CSRF_COOKIE’: ‘t80NcGNOBBoGgyV0LfP0hFEohVWd64GtYzQXycQQTGCSw3RjMt6AaHLpJE8jcJi2’, ‘XDG_SESSION_PATH’: ‘/org/freedesktop/DisplayManager/Session0’, ‘REQUEST_METHOD’: ‘GET’, ‘TERM’: ‘xterm-256color’, ‘DEFAULTS_PATH’: ‘/usr/share/gconf/ubuntu.default.path’, ‘WORKON_HOME’: ‘/home/tarena/my_env’, ‘XDG_SESSION_TYPE’: ‘x11’, ‘MANDATORY_PATH’: ‘/usr/share/gconf/ubuntu.mandatory.path’, ‘PATH’: ‘/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/tarena/anaconda3/bin:/opt/mongodb-linux-x86_64-ubuntu1604-3.4.10/bin’, ‘GTK2_MODULES’: ‘overlay-scrollbar’, ‘XDG_SESSION_DESKTOP’: ‘ubuntu’, ‘SHLVL’: ‘1’, ‘HTTP_REFERER’: ‘http://localhost:8000/01_request/’, ‘XDG_VTNR’: ‘7’, ‘USER’: ‘tarena’, ‘RUN_MAIN’: ‘true’, ‘HTTP_USER_AGENT’: ‘Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0’, ‘GDMSESSION’: ‘ubuntu’, ‘VTE_VERSION’: ‘4205’, ‘DBUS_SESSION_BUS_ADDRESS’: ‘unix:abstract=/tmp/dbus-GLbvZJivUO’, ‘VIRTUALENVWRAPPER_SCRIPT’: ‘/usr/local/bin/virtualenvwrapper.sh’, ‘DJANGO_SETTINGS_MODULE’: ‘Day07.settings’, ‘REMOTE_HOST’: ‘’, ‘OLDPWD’: ‘/home/tarena/Django’, ‘HTTP_COOKIE’: ‘csrftoken=t80NcGNOBBoGgyV0LfP0hFEohVWd64GtYzQXycQQTGCSw3RjMt6AaHLpJE8jcJi2; sessionid=fdx3g2c0s2je9evx69qg8wcv62dxlhv3’, ‘WINDOWID’: ‘69206026’, ‘SESSIONTYPE’: ‘gnome-session’, ‘wsgi.multithread’: True, ‘XDG_RUNTIME_DIR’: ‘/run/user/1000’, ‘LESSCLOSE’: ‘/usr/bin/lesspipe %s %s’, ‘HTTP_ACCEPT’: ‘text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8’, ‘XDG_DATA_DIRS’: ‘/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop’, ‘HTTP_HOST’: ‘localhost:8000’, ‘XDG_SESSION_ID’: ‘c2’, ‘LESSOPEN’: ‘| /usr/bin/lesspipe %s’, ‘LS_COLORS’: ‘rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.Z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.jpg=01;35:.jpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:’, ‘XDG_CURRENT_DESKTOP’: ‘Unity’, ‘SHELL’: ‘/bin/bash’, ‘GTK_IM_MODULE’: ‘fcitx’, ‘GDM_LANG’: ‘zh_CN’, ‘SESSION’: ‘ubuntu’, ‘SERVER_PROTOCOL’: ‘HTTP/1.1’, ‘SERVER_SOFTWARE’: ‘WSGIServer/0.2’, '’: ‘./manage.py’, ‘UPSTART_SESSION’: ‘unix:abstract=/com/ubuntu/upstart-session/1000/1524’, ‘GNOME_KEYRING_PID’: ‘’, ‘XDG_SEAT_PATH’: ‘/org/freedesktop/DisplayManager/Seat0’, ‘wsgi.version’: (1, 0), ‘HOME’: ‘/home/tarena’, ‘HTTP_ACCEPT_ENCODING’: ‘gzip, deflate’, ‘LANG’: ‘zh_CN.UTF-8’, ‘QT_ACCESSIBILITY’: ‘1’, ‘UPSTART_INSTANCE’: ‘’, ‘TZ’: ‘UTC’, ‘SCRIPT_NAME’: ‘’, ‘GATEWAY_INTERFACE’: ‘CGI/1.1’, ‘wsgi.input’: <_io.BufferedReader name=5>, ‘VIRTUALENVWRAPPER_PROJECT_FILENAME’: ‘.project’, ‘XAUTHORITY’: ‘/home/tarena/.Xauthority’, ‘HTTP_CONNECTION’: ‘keep-alive’, ‘DISPLAY’: ‘:0’, ‘QT_QPA_PLATFORMTHEME’: ‘appmenu-qt5’, ‘VIRTUALENVWRAPPER_HOOK_DIR’: ‘/home/tarena/my_env’}

      ================================================================

      1.forms模块
      1.forms的高级处理
      将Models和Forms结合到一起使用
      将Forms中的类和Models中的类关联到一起,实现属性的共享

      	1.在 forms.py中创建class,继承自 forms.ModelForm
      	2.创建内部类:Meta,关联Form 和 Model
      		属性:
      			1.model : 指定要关联的Model类
      			2.fields : 指定从Model中取哪些字段生成控件
      				1.取值 "__all__",全部的属性都要生成控件
      				2.取值 为列表,声明允许生成控件的属性名称
      			3.labels : 指定每个属性所关联的label,取值为 字典
      				labels = {
      					'属性名':'label文本',
      					'属性名':'label文本',
      				}
      2.内置小部件
      	1.什么是小部件
      		小部件(widget),表示的是生成到页面中的控件的类型以及其他的html属性
      	2.常用小部件
      		1.TextInput : type="text"
      		2.NumberInput : type="number"
      		3.PasswordInput : type="password"
      		4.EmailInput : type="email"
      		5.URLInput : type="url"
      		6.HiddenInput : type="hidden"
      		7.CheckboxInput : type="checkbox"
      		8.Textarea : <Textarea></Textarea>
      		9.Select :<Select></Select>
      	3.小部件的使用
      		1.继承自 forms.Form
      			1.基本版
      				只指定控件的类型
      				属性 = forms.CharField(
      					label='标签',
      					widget=forms.小部件类型
      				)
      				ex:
      				upwd = forms.CharField(
      					label='用户密码',
      					widget=forms.PasswordInput
      				)
      			2.高级版
      				指定控件类型之外还允许设置html属性
      				属性 = forms.CharField(
      					label='标签',
      					widget=forms.小部件类型(
      						attrs={
      							'html属性名':'属性值',
      							'html属性名':'属性值',
      						}
      					)
      				)
      		2.继承自 forms.ModelForm
      			class Widget2Form(forms.ModelForm):
      				class Meta:
      					model = Users
      					fields = "__all__",
      					labels = {
      						'属性1':'标签1',
      						'属性2':'标签2',
      					}
      					widgets={
      						'属性1':forms.小部件类型(attrs={}),
      						'属性2':forms.小部件类型(attrs={}),
      					}
      

      2.cookies
      1.什么是cookies
      cookies 是一种数据存储技术
      允许将一段文本保存在客户端(浏览器)上的一种技术,并可以长时间保存
      2.cookies的使用场合
      1.记住密码
      2.保存搜索关键词
      3.django 中使用cookie
      1.设置cookies的值(将数据保存到客户端)
      语法:
      响应对象.set_cookie(key,value,expires)
      key:cookie的名字
      value:cookie的值
      expires:保存时间,以s为单位
      ex:
      响应对象.set_cookie(‘uname’,‘zsf’,606024*366)
      1.不使用模板 (HttpResponse)
      resp=HttpResponse(“给客户端的一句话”)
      resp.set_cookie(‘key’,‘value’,expires)
      return resp
      2.使用模板 (render)
      resp=render(request,‘xxx.html’,locals())
      resp.set_cookie(‘key’,‘value’,expires)
      return resp
      3.使用重定向(HttpResponseRedirect / redirect)
      resp=HttpResponseRedirect(’/地址/’)
      resp.set_cookie(‘key’,‘value’,expires)
      return resp

      		练习:
      			1.登录操作
      			2.创建登录模板
      				用户名 :文本框
      				密码:密码框
      				记住密码:复选框
      			3.登录验证
      				去数据库验证 用户名 密码是否正确
      				如果正确的话,并且勾选了 记住密码的话,则将登录信息保存进cookie
      					将 用户id 和 登录名称保存进 cookie 即可
      	2.获取cookies的值(将数据从客户端中获取出来)
      		通过request.COOKIES 获取当前访问的站点下所有的cookies的信息
      		
      		练习:
      			完善登录操作
      			1.当用户访问 登录路径时
      				先判断cookies中是否有登录信息(uid,uname)
      			2.如果cookies中包含登录信息的话,直接跳往至首页,如如果cookies中不包含登录信息的话,则去往登录页
      

      3.session - 会话
      1.什么是session
      session(会话),实际上就是在服务器上为每个浏览器开辟一段空间,用于保存相关的请求信息
      2.session的使用场合
      session也是为了存储数据而存在的
      通常会把服务器端经常要用到的数据保存进去
      3.Django中使用session
      1.设置 session 的值
      request.session[‘key’]=value
      request.session.set_expiry(time) : 设置session的过期时间,如果设置为0的话,则表示关闭浏览器session就失效
      2.获取session的值
      value=request.session[‘key’]
      value=request.session.get(‘key’)
      3.删除session的值
      del request.session[‘key’]
      4.在 settings.py中,有关session的设置
      1.SESSION_COOKIE_AGE
      作用:设置sessionID在 cookies 中的保存时长
      ex:
      SESSION_COOKIE_AGE=606024
      2.SESSION_EXPIRE_AT_BROWSER_CLOSE
      作用:设置关闭浏览器时则清除服务器上对应的session空间
      ex:
      SESSION_EXPIRE_AT_BROWSER_CLOSE = True

      判断session中是否有登录信息,如果有的话,跳转至首页,否则,再判断cookies

      取出session中的数据发送到首页上

      {
      ‘uid’: ‘2’,
      ‘csrftoken’: ‘ssdUc15xwok8Gf4Ce7ghzcDkDO1Rc8rQaRMzcHonk7ksUOuQmqI39p78jdmk7X8Z’,
      ‘uname’: ‘tarena’
      }

      猜你喜欢

      转载自blog.csdn.net/qq_43219213/article/details/87278430