1、Python用具 - pip
1、作用:
Python的软件包管理器,有一些python包被集成到了pip中。只要被集成到pip中的包,都允许通过pip直接安装
2、安装 pip
sudo apt install python-pip(python2)
sudo apt install python3-pip(python3)
3、使用pip/ pip3
1、安装/下载/更新/删除 python包
1、安装python包(下载并安装)
sudo pip3 install SomePackage
sudo pip3 install PyMySQL==0.7.11(如果不写版本号默认为最新的版本)
2、下载python包(值下载不安装)
sudo pip3 download SomePackage
3、删除python包
sudo pip3 uninstall SomePackage
4、更新(升级)python包
sudo pip3 upgrade SomePackage
2、查看当前环境中所安装的包
pip3 list
3、搜索
pip3 search SomePackage
4、展示
pip3 show SomePackage
5、记录现有环境的python包
1、pip3 freeze > requirements.txt
将当前python环境中所安装的内容打包成一个txt文件
2、pip3 install -r requirements.txt
允许在当前系统下,逐一安装requirements.txt中所有列出的内容
2、Python工具 - VirtualEnv
1、什么是VirtualEnv - 虚拟环境
virtualEnv是python中的虚拟环境,在做python应用开发时,如果不想在大的python环境中安装各种各样的包的话,则可以虚拟出一个python环境,可以让虚拟环境专门为某一应用而存在。允许在虚拟环境中安装各种包且不影响大的python环境
2、安装VirtualEnv
sudo pip3 install virtualenv
3、创建 和 使用 虚拟环境
1、准备工作
mkdir my_env
cd my_env
2、创建虚拟环境
virtualenv 虚拟环境名称
示例:virtualenv default
创建指定版本的虚拟环境
virtualenv -p /usr/bin.python2.7 名称
virtualenv -p /usr/bin.python3.6 名称
3、启动虚拟环境
注意:不能在bin目录中启动虚拟环境(根目录下的bin目录)
source bin/activate
4、退出虚拟环境
deactivate
5、删除虚拟环境
rm 虚拟环境目录 -rf
注意:在虚拟环境中使用pip安装和卸载内容时,不要使用sudo进行授权,如果使用则操作的是大环境
4、虚拟环境管理工具 - VirtualenvWrapper
1、作用
第三方的管理工具,能够快速,高效且方便的管理虚拟环境
2、安装虚拟环境管理工具
sudo pip3 install virtualenvwrapper
3、配置virtualenvwrapper
在~(家目录)目录下,有一个终端管理文件 .bashrc(在~目录下,输入ll查看)
配置.bashhrc,以便在启动终端时,就自动启动虚拟环境管理工具
修改.bashrc: sudo vi .bashrc
在.bashrc 最底部增加一下内容
1、export WORKON_HOME=~/my_env:
将~/my_env 作为虚拟环境的管理目录,所有使用virtualenvwrapper创建的虚拟环境都默认保存于此
2、如果系统中包含多个python执行环境的话,则添加一下内容
export VIRTUALENVWRPPER_PYTHON=/usr/bin/python3
3、source /usr/local/bin/virtualenvwrapper.sh:默认启动刮管理工具
4、在~目录下,执行一遍.bashrc
source .bashrc
4、使用虚拟环境管理工具
1、创建并进入虚拟环境管理工具
1、mkvirtualenv 虚拟环境名称
2、mkvirtualenv --python=/usr/bin/python2.7 env2.7
2、查看当前所维护的所有虚拟环境
workon
3、切换虚拟环境
workon 虚拟环境名称
4、退出虚拟环境
deactivate
5、删除虚拟环境
rmvirtualenv 虚拟环境名称
3、WEB 与 服务器
1、WEB:表示用户可以浏览的网页(HTML,CSS,JS)
2、服务器:专门给用户提供服务的一台机器
1、硬件 与 软件
硬件范畴:一台主机
软件范畴:一个能够接收用户请求并给出响应的程序
1、APACHE
2、TOMCAT
3、IIS(Internet Information Service)
4、Nginx
2、作用:
1、存储WEB上的信息(网页,图片,音视频,css,js)
2、能够处理用户的请求(request)并给出响应(response)
3、能够执行服务器端程序:如查询数据库
3、WEB与服务器的关系
WEB需要放在服务器上才能够被用户访问
运行在服务器端的程序,可以由不同的语言来编写
Java语言-->JSP
C#语言-->ASP>NET
PHP语言-->php
Python语言-->Django
4、网站请求的全过程
1、用户:输入域名,通过域名解析(DNS)器得到IP地址
2、向服务器发送http(开80端口)/https(开440端口)请求
3、传输层TCP协议,经过网络传输和路由解析
4、WEB服务器接收HTTP请求
5、服务器处理请求内容,并进行必要的数据交换(我们需要做的事情)
6、将响应的内容发回给浏览器(响应)
7、浏览器解析HTML
8、显示解析好的内容
4、框架
1、什么是框架
框架是一个为了解决某些开放性问题而存在的一种结构。框架本身提供了最基本的功能,我们只需在这些基本功能上构建自己的操作即可。
2、框架的优点
1、快速开发 - 基本功能已经提供好了
2、可以解决大部分问题
3、bug少,稳定性较高
3、框架的分类
1、前端框架
处理前端内容(HTML,CSS,JS)
2、后端框架
处理服务器程序的
Spring -Java
3、全栈框架
包含WEB整体的解决方案,包括开发框架,运行环境
Rails(Ruby)
Django(Python)
4、Python的WEB框架
1、Django:重量级的Python Web框架
2、Tornado:异步框架
3、Flask:轻量级框架,直接引入模块即可使用
4、Webpy:轻量级框架
5、Web2py:全栈框架,webpy的加强版
1、设计模式 与 框架模式
1、设计模式
设计模式,是一套被反复使用,多数人知晓并经过分类的代码设计经验的总结,是为了解决一些通用性问题的
目的:重用代码并保证代码的可靠性
官方认证的设计模式有23中:单列模式,抽象工厂模式,观察者模式等 《大话设计模式》
2、框架模式
代码的重用,框架模式是解决如何设计程序框架的代码,在框架模式中会包含多种的设计模式
如:MVC,MTV,MVVM,ORM,…
1、MVC
M:Models,模型层,
在程序中主要处理数据,负责在数据库中对数据进行存取操作(CRUD)
V:Views,视图层
应用程序中处理显示的部分内容(HTMl,JSP)
C:Controllers,控制器层
处理用户交互的部分,通常负责从模型中取出数据,再进行业务的处理,最后将数据给视图,并将视图给客户端
2、MTV
M:Models 模型层,
模型层,负责数据库建模以及CRUD的操作
T:Templates 模板层
用于处理用户显示的部分内容,如:html
V:Views 视图层
处理用户交互部分,从模型中获取数据,再将数据给模板,在显示给用户
2、Django框架
1、什么是Django
是一个开源框架,2005年发布,采用python语言开发的。早期Django是做新闻和内容管理的网站的,提供了非常强大的后台管理系统,采用的是MTV框架模式
2、Gjango的优缺点
1、优点
1、开源框架,有完美的文档支持
2、解决方案比较完整,内部功能也比较多
3、提供完整的路由系统,优雅的URL解析方式
4、自助式的后台管理
2、缺点
1、耦合度偏高
3、Django的安装
1、Linux中的安装
1、查看已安装的Django
1、进入到虚拟环境中
2、进入到python的交互模式中
3、在交互模式中输入
1、import django
2、django.VERSION
2、在线安装 - 使用 pip
1、终端中输入
pip install django(安装django的最高版本)
pip install django==1.11.8
注意:在虚拟环境中不要使用sudo
2、离线安装
1、下载所需要的django包
2、在Linux中解压django
tar - xvf Gjango-1.11.8.tar.gz
3、进入到Django文件夹中
4、安装
python setup.py install
2、Windows中的安装
1、在线安装
控制台: pip3 install django==1.11.8
2、离线安装
1、下载django安装包
2、解压django包
3、进入到django包中
python setup.py install
4、使用Django
1、创建Django项目
直接使用django-admin去创建Django项目
1、找到项目文件夹(自定义)
2、使用django-admin 指令
django-admin startproject 项目名称
2、启动Django项目
1、进入到项目文件夹中
2、通过manage.py 启动项目
1、
python manage.py runserver
或 ./manage.py runserver
只能在本机访问
http://localhost:8000
http://127.0.0.1:8000
2、
python manage.py runserver 0.0.0.0:8000
或 ./manage.py runserver 0.0.0.0:8000
允许在局域网内访问。可以通过IP地址访问,但是需要将setting.py文件中ALLOWED_HOSTS = []修改为ALLOWED_HOSTS = ["*"]
5、Django结构介绍
1、manage.py
负责执行django中的各项操作的文件,又叫命令脚本文件
如:
1、启动服务
2、创建应用
3、创建管理员、用户
….
2、主文件夹(名称与项目名称相同)
存放项目的最基础的配置文件
1、__init__.py
项目初始化文件,每当服务器启动的时候,会自动执行,如果有自定义的初始化操作,需要放在该文件中
2、urls.py
项目的基础url(路由)配置文件
路由:去哪里找执行的程序
3、wsgi.py
配置应用服务器的文件,暂时不用
4、settings.py(重要)
项目的主设置文件:应用:模板,数据库,语言,时区….
1、BASE_DIR:项目的绝对路径
2、DEBUG:调试模式
开发过程中,推荐使用Ture,上线运行时,必须改为False
3、ALLOWED_HOSTS
设置允许访问本地项目的地址列表,如果不设置的话,只能本机访问,推荐用"*",表示任何机器都允许访问当前项目
4、INSTALLED_APPS
指定已经安装的应用,如果有自定义应用的话,需要在此注册
5、MIDDLEWARE:注册中间件
6、ROOT_URLCONF:指定项目的基础路由配置文件
7、TEMPLATES:指定模板的信息
8、DATABASES:指定数据库的信息
9、LANGUAGE_CODE:指定语言,允许修改为zh-Hans
10、TIME_ZONE = 'UTC':指定时区,建议改为Asia/Shanghai
6、settings的加载流程
1、先加载globals_settings.py
位于:/home/xdl/my_env/env3.5/lib/python3.6/site-packages/django/conf/globals_settings.py
2、再加载项目中的settings.py
注意:如果globals_settings中的内容与项目settings中的内容冲突的话,优先使用项目中的settings中的内容
7、初始 django-admin 和 mangage.py
1、在终端输入django-admin命令
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
runserver
sendtestemail
shell:python3 manage.py shell ,进入django的交互环境,
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject#创建项目
test
testserver
2、进入项目主目录文件夹,输入./manage.py
[auth]
changepassword #修改密码
createsuperuser #创建超级用户
示例:
1、首先需要创建一张用于存储用户信息:./manage.py migrate
2、创建用户:./manage.py createsuperuser
[contenttypes]
remove_stale_contenttypes
[django]
check
compilemessages
createcachetable
dbshell #进入到Django数据shell交互模式
diffsettings
dumpdata
flush
inspectdb #将数据表直接导出为Models
loaddata
makemessages
makemigrations#创建数据库日志文件,记录Models的改动
migrate #将数据库日志文件同步到数据库中
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp #创建应用
startproject
test
testserver
[sessions]
clearsessions
[staticfiles]
collectstatic
findstatic
runserver #启动服务
8、URL的使用
1、urls.py
默认在主文件夹中,包含所有的地址映射。
每当一个请求产生后,都会到urls.py中进行地址的匹配,匹配上后再找对应的处理程序(View视图)去处理
2、测试
1、在主文件夹中,创建views.py
作用:包含所有定义好的视图(处理程序)
内容包括:
from django.http import HttpResponse
def fun_views(request):
'''视图,处理用户的请求并给出响应
request:表示用户的请求信息
HttpResponse:响应给客户端的内容'''
return HttpResponse("Hello django")
2、在urls.py中追加
from .views import *
urlpatterns = [
url(r'^admin/',admin.site.urls),
//如果访问路径是fun/ 的话,则交给fun_views视图处理函数去处理
url(r'^fun/$',fun_views),//如果这里添加了自定义视图处理函数时,localhost:8000将会失效
//如果请求的URL在这里可以匹配多个,则只能执行第一个匹配到的
]
3、url函数
url函数的语法:
url(regex,views,kwargs=None,name=None)
1、regex:正则表达式,匹配请求的url
2、views:url处理的视图函数,通常都是自定义的
3、kwargs:字典,用来向views传参
4、name:字符串,给url()起一个别名,主要在模板中匹配{%url%}一起使用
4、url向view传参
1、使用正则表达式传参
使用正则表达式的子组传参,使用()
urlpatterns=[
//访问路径必须是fun
url(r'^fun/$',fun_views),
//访问路径必须是fun
url(r'^fun/$',fun_views),
url(r'^fun/(\d+)',fun_arg1_views),
]
注意
1、在url()中,一个子组()表示一个参数
2、在views.py中,对应的处理函数要根据url()中子组的个数,相应的定义参数,定义的参数要位于request之后
练习:
1、访问地址:localhost:8000/18/0223/15,如何获取18 0223 15
def fun_arg3_views(request,num1,num2,num3):
return HttpResponse("%s %s %s"%(num1,num2,num3));
url(r'^(\d{2})/(\d{4})/(\d{2})$',fun_arg3_views),
2、使用url()第三个参数,字典传参
urlpatterns=[
url(r'^showname/$',show_views,{'name':"zhang",'age':25}),
]
views.py:
def show_views(request,name,age):
return HttpResponse(name+':'+str(age))
注意:
1、视图处理函数中,必须声明参数
2、参数的名称 和 位置 必须要与字典中的名称和位置保持一致
3、Django中的应用
1、什么是应用
应用是网站中的一个独立的模块,包含独立的显示信息
在项目主文件夹中一般不处理其他的请求,主要就做初始化设置 以及 地址的分发
实际操作中,会将请求交给不同的应用去处理
2、创建应用
1、命令: ./manage.py startapp 应用名称
2、在settings.py中注册应用:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
]
3、应用的结构组成
1、migrations 目录
存放数据库日志文件,是一个django与数据库交互的中间文件
2、__init__.py
应用的初始化操作文件
3、admin.py
应用的后台管理配置文件
4、apps.py
应用的属性设置文件,不需改动
5、modles.py
Modles模型文件
6、tests.py
测试模块,通常不用
7、views.py
定义视图的py文件
练习:
创建应用,并进行注册
在day02_exer 中创建应用
1、index - 主页面的应用
./manage.py startapp index
2、news - 新闻的应用
./manage.py startapp news
3、sports - 体育的应用
./manage.py startapp sports
4、musics - 音乐的应用
./manage.py startapp musics
在settings.py中的INSTALLED_APPS列表中添加以上应用
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'index',
'news',
'sports',
'musics',
]
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
]
urlpatterns += [
url(r'^music/', include('music.urls')),
url(r'^sport/',include('sport.urls')),
url(r'^news/',include('news.urls')),
#匹配空的时候一定要放在最后
url(r'^', include('index.urls')),
]
1、Django模板(Template)
1、什么是模板
就是一个网页,可以被view响应给用户
目的是为了解决复杂的显示问题
2、模板的设置
1、BACKEND:指定模板的搜索引擎,不用改动(就是指定到哪里搜索模板)
2、DIRS:指定模板所存放的目录,如果DIRS为空的话并且APP_DIRS为True,那么django会自动搜索每个应用中的templates文件作为模板管理目录
DIRS = ['index.trmp','music.temp']
推荐:
1、DIRS保持为空
2、在每个应用中,创建一个templates的文件夹
3、APP_DIRS:值为boolean类型
True:首先从DIRS中指定的文件夹中查找模板,如果没有找到指定模板的话,则再搜索templates目录
3、模板的加载方式
1、使用loader 获取模板,通过HttpResponse进行响应
from django.template import loader
def xxx(request):
#1、通过loader加载模板
t = loader.get_template('show.html')
#2、将模板渲染成字符串
html = t.render({})
#3、通过HttpResponse响应回去
return HttpResponse(html)
说明:
render({}),字典中的是数据,会传入html文档中,在HTML中通过{{字典的键}}取值,{{num1}}
render({}),字典参数,可以通过locals(),获取该函数中的局部变量的字典,进行传递
2、使用render直接加载
return render(request,'模板名称',{})
4、url()的name参数
urlpatterns = [
url(regex,views,kwargs=None,name=None)
]
name:定义当前url的别名,允许在Template中使用该别名来找到对应的url(反向解析)
反向解析:通过name 的值来匹配出对应的regex路径
在Django模板中使用name实现连接
{% url 'name值' %}
如果url中有参数需要{% url 'name值' 参数1 参数2 …%}
在视图中实现name别名反向解析出对应的URL地址
需要引包:from django.shortcuts import reverse
语法:
1、无参数解析:reverse("别名")
2、带参数解析:reverse("别名",args = (参数1,参数2….))
from django.shortcuts import render
from django.http import HttpResponse
from django.urls import reverse
def index_views(request):
return HttpResponse("news index_views")
def reverse_views(rquest):
#反向解析url(不带参数),/news/reverse
#url = reverse("reverse")
#反向解析url(带参数),/news/reverse/2018/08
url = reverse('reverse_args',args=(2018,''))
return HttpResponse("反向解析出的URL:"+url)
5、模板的语法
1、变量
1、 作用:允许将后端的数据传递给模板(html),在模板中,会根据变量的实际值进行显示
2、在Django中允许传递给模板作为变量的数据类型
数字,字符串,列表,元组,字典,函数,对象,类。 集合不可以
3、变量语法
变量们必须要封装到字典中才能传递给模板
1、使用render加载模板
dic = {
’变量1’:‘值1’,
‘变量2’:‘值2’,
….
}
return render(request,'xx/html',dic)
2、使用loader加载模板
dic = {
’变量1’:‘值1’,
‘变量2’:‘值2’,
….
}
t = loader.get_template('x.html')
#渲染成字符串是需要传递变量字典到模板中
html = t.render(dic)
return HttpResponse(html)
4、在模板中使用变量:
{{变量名}}
如果要取列表,字典,元组中的值要通过变量名.下标 或 变量名.键
def var_views(request):
#声明变量字典
l = ['金毛狮王','白眉鹰王','青']
t = ('潘林连','西门庆','武大郎')
dic = {
'SHZ':"水浒传",
'xyj':"西游记",
'hlm':'红楼梦'
}
def fun():
return '函数'
class Dog(object):
name = '阿拉斯基'
def eat(self):
return '吃狗粮'
vars = {
'num':15,
'str':'模板中的字符串变量',
'tup':t,
'list':l,
'dic':dic,
'fun':fun(),#等价于'fun':fun
'dog':Dog(),#等价于Dog
}
return render(request,'02\_var.html',vars)
2、标签
1、什么是标签
允许嵌套一些服务器端的逻辑运算到模板中
2、语法
{% %}
3、常用标签
1、{% if 条件 %} …{% endif %}
接受:not and or
但是 :and 和 or 不能同时出现
以下内容当成False处理:
空[]
空()
空{}
数字:0
空字符串
特殊对象:None
2、{%if 条件 %}…{%else%}…{%endif%}
3、
{%ifequal 值1 值2%}…{%endifequal%}:判断值1与值2是否相等
{%ifequal 值1 值2%}…{%else%}…{%endifequal%}
4、{% for 变量 in 列表|元组|字典%}{%endfor%}
允许使用的内置变量(免声明)
forloop
1、forloop.counter:记录循环的次数
2、forloop.counter0:同上,但从0开始
3、forloop.revcounter:记录未被遍历的数量
4、forloop.revcounter0:同上,从0开始
5、forloop.first:布尔值,标记是否为第一个项目
6、forloop.last:布尔值,表示是否为最后一个项目
{% for str in l %}
5、{%url%}
6、{%static%}
7、{%extends%}:用作模板继承
8、comment 标签
作用:在服务器端就被注释的内容,不会被渲染到客户端的
>:客户端注释会被渲染到客户端,在其中的{{ 服务器代码}},回去执行解释
3、过滤器
1、作用
在显示变量之前,允许对数据进行筛选或改变
2、过滤器的语法
{{var|过滤器}}
3、常用过滤器
1、{{var|upper}}:将var的数据变为大写
2、{{var|lower}}:将var的数据变为小写
3、{{var|add}}:
4、{{var|floatformat:n}}:将var四舍五入到n为小数
5、{{value|truncatechars:n}}:将value截取保留至n位字符(包含三个点…)
自定义标签和过滤器
步骤:
1、在应用目录下创建templatetags目录
2、在templatetags创建模块文件,并导入Django内部方法
3、在模板最上方中加载自定义的模块文件,{% load 模块文件名%}
自定义过滤器
1、在templatetags目录下创建python模块,例如命名为tags.py
from django import template
register = template.Library()
@register.filter
def value_verification(value): # value为前端传递的参数
'''最多传递两个参数'''
try:
int(value)
return True
except:
return False
{% load app01_func %}
{% if load|value_verification %}
{{ num }} is a valid int number.
{% else %}
{{ num }} is letter.
{% endif %}
自定义标签
1、simple_tag的代码方式与filter一样,不同的是在装饰器部分和前端调用的方式不同
from django import template
register = template.Library()
@register.simple_tag
def value_verification(value): # value为前端传递的参数
'''可以传递多个参数'''
try:
int(value)
return True
except:
return False
2、前端模块中调用{% value_verification num %}
filter 和 simple_tag的区别
1、filter可以用在if 条件判断中,但是最多只能有两个参数,可以将多个参数用特定字符拼接成一个字符串传递给后端,后端通过拆分获取多个参数
2、simple_tag不能用在if、for语句中,可以传递多个参数
3、模板中的调用方式不同
1、filter将我们指定的函数变成了返回值可执行的方法{{ 参数1 | value_verification:参数2 }},冒号后面不能有空格
2、simple_tag将函数功能变为标签功能{% value_verification 参数1 参数2…… as 返回结果的别名 %}
4、静态文件的处理
1、什么是静态文件
在Django中,不被解释器动态解析的文件就称为静态文件,在Django中,物理路径(磁盘中真是存在的)是无法找到静态文件的
模板中所用到的css,js,image等一些资源文件都是静态文件
2、Gjango中静态文件的处理
需要在settings.py中设置静态文件的访问路径 和 存储路径
1、STATIC_URL:设置静态文件的访问路径
STATIC_URL = '/static/'
2、STATICFILES_DIRS:设置静态文件的存储路径
1、STATICFILES_DIRS = (BASE_DIR,'static')
2、STATICFILES_DIRS = (os.path.join(BASE_DIR,'静态文件目录名'))
静态文件目录存放位置:
1、所有应用中创建一个同名目录
2、项目的根目录处也可以创建一个同名文件
3、访问静态资源
1、
2、使用{%static%}访问静态资源
{%static%}:表示的就是静态文件资源的访问路径(就是setting.py中STATIC_URL的值,STATIC_URL = '/static/')
1、模板的最顶层增加{%load static%}
2、使用静态资源文件时
<img src="{%static 'images/huiyuan.jpg'%}"
5、模板的继承
1、什么是模板的继承
当多个模板(网页)具备大部分相同的内容时,就可以使用继承的方式,将相同的内容继承过来,在增加/修改属于自己的内容即可
2、模板继承的语法
1、在父模板中增加{%block 名称%}…{%endblock%}
说明:名称不能重复
2、在子模板中
1、在最顶层第一句话增加:
{%extends '父模板的名称'%}
2、增加block标记,编写属于自己的内容
{%block 名称%}//这里的名称要与父模板{%block 名称%}中的名称相同
属于子模板中自己的内容
//一旦引用次标记,则此处不再显示父模块中的内容
{%endblock%}
2、Django模型(Model)
1、什么是模型
模型,就是根据数据中数据表的结构而创建出来的class。
数据库中的每一张表到编程语言中就是一个class
数据库表中的每一个字段(列)可以被构建成class中的一个成员变量(属性),并且在模型中,完成对数据库的CRUD操作
C:Create
R:Retrieve(检索查找)
U:Update
D:Delete
2、创建 和 使用模型 - ORM
1、什么是ORM
ORM:Object Relational Mapping(对象关系映射)
简称:ORM, O/RM, O/R Mapping
三大特征:
1、数据表到类(class)的映射
允许将表自动生成一个类,也允许将一个类自动生成一张表
2、数据类型的映射
允许将表中字段的类型自动生成到编程语言中对应的数据类型,也允许将编程语言中的数据类型生成数据表中对应的字段类型
3、关系映射
数据库中表的关联关系:
一对一,一对多(多对一),多对多
将表中的关联关系也映射到编程语言的class中,通过创建对象的关系来完成映射
允许将类与类之间的关系自动映射成表与表之间的关系
class A(object):
name = None
class B(object):
a = A()#在表中通过外键进行关联
2、ORM的优点
1、提高了开发效率,能够自动完成实体类到数据表的映射,
2、可以省略庞大的数据访问层,即便不用SQL编码(语句),就能够完成对数据的CRUD操作
3、创建 和 配置数据库
1、创建数据库(支持中文)
create database webdb default charset=utf8
create database webdb default charset utf8 collate utf8_general_ci
2、Django中数据库的配置
settings.py中配置数据库信息
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'webdb',
'USER': 'debian-sys-maint',
'PASSWORD':'Lo0r79JmxvMFNtA2',
'HOST':'localhost',
'PORT':'3306',
}
}
1、ENGINE:引擎
django.db.backends.mysql
2、NAME:要连接到的数据库名称
3、USER:用户名称
4、PASSWORD:密码
5、HOST:连接的主机,本机的话localhost/127.0.0.1/不写
6、PORT:端口,3306
4、安装pymysql
注意:Django中要连接MySQL数据库的话要依赖于MySQLdb,通过pymysql解决问题
pip install pymysql==0.7.11
5、在主文件夹找找到__init__.py写入
import pymysql
pymysql.install_as_MySQLdb()#转换为MySQLdb
6、启动django
./manage.py runserver
4、数据库的同步操作
1、./manage.py makemigrations
作用:将每个应用下的models.py文件生成一个数据库的中间文件(映射成一个数据库日志文件),并存放在migrations目录中
2、./manage.py migrate
作用:将每个应用下的migrations目录中的中间文件(日志文件)同步到数据库中
当migrations目录中没有中间文件时,会创建Django中自带的数据表
5、编写Models(重难点)
1、注意:
1、Models中的每个class都称之为 模型类(Model)或实体类(Entry)
实体:数据表中的一行记录,就是一个实体
实体完整性:确保每张表中的数据不能有重复的,数据表中的主键,是实现实体完整型的方式之一
2、Models中的每个实体类,必须继承自models.Model
2、示例:
在models.py中
from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=20)
website = models.URLField()
from django.db import models
import datetime
#实体类:Publisher
#对应到数据库中的一张,表表名为index_publisher(应用名_实体类名小写)
#该类中的每个属性,会对应到数据表中的每个字段啊
class Publisher(models.Model):
name = models.CharField(max_length=30,deafult='匿名')
address = models.CharField(max_length=60)
city = models.CharField(max_length=30)
country = models.CharField(max_length=30)
website = models.URLField()
class Author(models.Model):
name = models.CharField(max_length=30)
age = models.IntegerField()
email = models.EmailField(null=True)
class Book(models.Model):
title = models.CharField(max_length=50)
publication_date = models.DateField(default=datetime.datetime.now())
6、Django中的字段类型以及字段选项
1、字段类型(Field Types):映射到数据库表中的数据类型
1、BooleanField():tinyint()
2、CharField():varchar()
3、DateField():date
4、DateTimeField():datetime(6),6位精度 2018-08-27 16:43:20.000000
5、FloatField():double()
6、FileField():varchar(100)
7、EmailField():varchar(254)
8、IntegerField():int(11)
9、ImageField(upload_to=None):varchar(100)存放文件路径
uimg=models.ImageField(upload_to='images/users/')
10、URLField():varchar(200)
11、DecimalField(max_digits=7,decimal_places=2):decimal(7,2),通常用来表示钱
12、TextField():longtext()存放大量数据
2、字段选项:对生成的字段的说明信息
1、null:是否允许为空,默认为False
name = models.CharField(max_length=30,null=True)
2、default:为该字段设置默认值
name = models.CharField(max_length==30,default="匿名")
3、db_cloumn
指定当前属性(字段)对应到数据库表的列名,如果不指定则采用属性名作为列名
3、说明:
如果在原先实体类中添加属性(字段)时,必须给这个字段设置为允许为空(null=True)或者给一个默认值default=‘值’,否则会有如下提示
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit, and let me add a default in models.py
7、数据的导入和导出(数据迁移)以及版本切换
1、版本切换
./manage.py migrate 应用名称 版本号
./mansge.py migrete index 0001 //会将原先已经映射的数据表删除
2、数据库的导出
1、mysqldump -u… -p 数据库名 >文件.sql
导出所有的表结构以及数据
2、mysqldump -u… -p -d 数据库名 >文件.sql
只导出所有的结构
3、数据库的导入
mysql -u.. -p 数据库名 < 文件.sql
4、通过数据库自动导出Models
./manage.py inspectdb >文件名.py
表名index_book变为实体类名为IndexBook
class IndexBook(models.Model):
title = models.CharField(max_length=50)
publication_date = models.DateField()
class Meta:
managed = False
db_table = 'index_book'
1、模型的数据库操作方法(CRUD)
1、通过视图向DB中增加数据
1、Entry.objects.create(属性=值,属性=值)
返回值:创建好的实体,
Author.objects.create(name='王宝强',age=33,email='wangbaoqiang@green.com')
2、创建一个实体对象,并通过save()方法完成增加
obj = Entry(属性=值,属性=值)
obj.save()
3、通过字典创建实体对象,在调用save()
dic = {
"name":"xx",
"age": ,
"email":"xx"
}
obj = Author(**dic)
obj.save()
示例:
dic = {"name":"陈羽凡","age":38,"email":"chenyufan@green.com"}
obj = Author(**dic)
obj.save()
def add_views(request):
#方法1、向Author实体中增加一条记录
ret = Author.objects.create(name='老舍',age=85,email='laoshe@163.com')
return HttpResponse(ret)#返回一个实体类对象,age是str,int都可以
#方法二
author = Author(name='巴金',age=75,email='bajin@163.com')
ret = author.save()
return HttpResponse(ret)#返回值为None
#方法三
dict = {
'name':'冰心',
'age':80,
'email':'bingxin@163.com',
}
author = Author(**dict)
ret = author.save()
return HttpResponse(ret)#返回None
2、查询操作(重难点)
所有的查询都要在Entry.objects.基础上完成
1、基本查询操作
语法:all()
用法:Entry.objecsts.all()
返回:QuerySet(查询结果集,是一个封装了若干对象的列表)
def query_views(request):
#查询Author实体中所有的数据
#返回一个列表,其中封装了若干的对象
authors = Author.objects.all()
for au in authors:
print(au.name,au.age,au.email)
return HttpResponse('query ok')
2、查询接口
1、all()
Entry.objects.all()
相当于:select * from …
2、查询指定列的操作
语法:values("列名1",‘列名2’…)
Entry.objects.values('name')
相当于:select name from …
作用:查询所有记录的某一列的值
返回值:QuerySet(查询结果集,是一个封装了若干字典的列表)
注意:values()可以用在QuerySet(查询结果集)后面比如:all().values()
def query_views(request):
#查询Author实体中name 和 age的信息
authors = Author.objects.values('name','age')
print(authors)
# < QuerySet[
# {'age': 85, 'name': '老舍'},
# {'age': 85, 'name': '老舍'},
# {'age': 75, 'name': '巴金'},
# {'age': 80, 'name': '冰心'}] >
for au in authors:
print(au['name'],au['age'])
# 老舍 85
# 老舍 85
# 巴金 75
# 冰心 80
return HttpResponse('ok')
3、values_list('列1',‘列2’)
Entry.objects.values_list("name","age")
相当于:select name,age from…
返回值:QuerySet,是一个有若干元祖所组成的列表:
注意:values_list()可以用在QuerySet(查询结果集)后面比如:all().values_list()
def query_views(request):
#查询Author实体中name 和 age的信息
authors = Author.objects.values_list('name','age')
print(authors)
#< QuerySet[
# ('老舍', 85),
# ('老舍', 85),
# ('巴金', 75),
# ('冰心', 80)] >
for au in authors:
print(au[0],au[1])
# 老舍 85
# 老舍 85
# 巴金 75
# 冰心 80
return HttpResponse('ok')
4、get()
只查找一条记录是使用,也只能返回一条记录,如果查询返回多条记录的话,则报错
Entry.objects.get(id=1)
相当于:select * from …. where id=1
返回值:Author object
注意:查询多于一条记录或者没有查询到结果都会抛出异常
1、get() returned more than one Author -- it returned 2!(Exception Type: MultipleObjectsReturned)
2、Author matching query does not exist(Exception Type: DoesNotExist)
5、exclude()
作用:对给定条件取反
Entry.objects.exclude(id=1)
相当于:select * from …where not id=1
返回值:
Entry.objects.exclude(id=1,age=33)
相当于:slect * from …where not(id=1 and age=3)
6、order_by()
Entry.objects.order_by('列名1',‘列名2’…)
指定按照字段进行排序,如果是多个字段,中间用,逗号隔开。默认是按照升序排列,需要降序的话,只需在列名前加”-“符号即可
返回值:QuerySet(查询结果集,是一个封装了若干对象的列表)
def query_views(request):
#查询Author实体中的数据按照年龄升序排列
authors = Author.objects.order_by('age')
print(authors)
#< QuerySet[
# < Author: 巴金 >,
# < Author: 冰心 >,
# < Author: 老舍 >,
# < Author: 老舍 >] >
for au in authors:
print(au.name,au.age)
#巴金 75
#冰心 80
#老舍 85
#老舍 85
return HttpResponse('ok')
7、filter()
根据自定义条件查询结果集,可以是一个,也可以是多个,多个的话,条件用,逗号隔开。
如果是多个条件的话,其内部是使用AND来进行条件连接的
返回值:QuerySet(查询结果集,是一个封装了若干对象的列表)
1、使用Entry的属性来作为filter()的条件
示例:
1、Author.objects.filter(id=1)
相当于:select * from author where id=1
2、Author.object.filter(id=1,age=33)
相当于:select * from author where id=1 and age=3
2、使用Field Lookups(查询谓词),完成复杂条件查询
查询谓词:每一个独立的查询谓词就是一个独立的查询条件,所有支持使用查询条件的位置处,都允许适应查询谓词,get(),filter(),exclude()
语法:属性__查询谓词=,双下划线
1、__exact
作用:等值判断
Author.objects.filter(id__exact=1)
select * from author where id=1
查看文档:https://docs.djangoproject.com/en/2.1/ref/models/querysets/
def query_views(request):
#查询Author实体中邮箱属性包含字符a
authors = Author.objects.filter(email__contains='a')
return render(request,'query.html',locals())
2、子查询
inner = Author.objects.filter(name__exact="王宝强").values("age")
authors = Author.objects.filter(age__gt=inner)等价于authors = Author.objects.filter(age__gt=inner[0]['age'])
3、修改操作
1、修改单个对象
1、通过get()获取要修改的实体对象
2、通过实体对象修改属性值
3、在通过实体对象的save()函数,实现保存
auth = Author.objects.get(id=1)
auth.name='宝强.王'
auth.age = 45
auth.save()
2、批量修改(修改查询结果集的值)
调用update()函数即可
Author.objects.all().update(属性=值,….)
说明:不能批量修改id
4、删除操作
1、删除单个对象
obj = Author.objects.get(id=1)
obj.delete()
2、批量删除
Author.objects.all().delete()
5、F()操作 和 Q()操作
1、F()操作
作用:在执行中获取某列的值
语法:F(‘列名’)
from django.db.models import F
Author.objects.all().update(age=F('age')+10)
2、Q()操作
作用:在查询条件中完成或(or)的操作
语法:
from django.db.models import Q
Q(条件1)|Q(条件2)
Author.objects.filter(id=1,age=35)//查询id为1并且age为35
Author.objects.filter(Q(id_exact=1)|Q(age=35),name='王')//查询id为1或者age为35,并且那么为王的
用法二:
q = Q()
q.connector = 'or'
q.children.append(('id_exact',1))
q.children.append(('age',35))
Author.objects.filter(q)//查询id为1或者age为35
6、原生的数据库操作方法
1、查询
函数:raw()
语法:Entry.objects.raw(sql语句)
2、增删该
def sql(requset):
with connection.cursor() as cursor:
sql = 'delete from index_author;'
cursor.execute(sql)
return render(……)
7、转发 与 重定向
1、转发:
转发就是将用户的请求发给另外一个视图进行处理,并将处理结果返回给用户请求的视图,最后响应给用户
表现:地址栏不会发生改变
原因:只有一次请求,所以地址栏就是最初请求的地址
def query_views(request):
authors = Author.objects.filter(isActive=True)
return render(request,'query.html',locals())
def delete_views(request,id):
author = Author.objects.get(id=id)
author.isActive=False
author.save()
return query_views(request)
2、重定向:(推荐使用)
重定向就是告知并响应给用户哪个视图可以处理用户的请求,然后用户在根据响应的地址进行请求,最终得到结果
表现:地址栏会显示最后一次请求的地址
原因:重定向导致浏览器向服务器发送了两次请求
from django.http import HttpResponseRedirect
def query_views(request):
authors = Author.objects.filter(isActive=True)
return render(request,'query.html',locals())
def delete_views(request,id):
author = Author.objects.get(id=id)
author.isActive=False
author.save()
#重定向,参数是要重定向的地址
return HttpResponseRedirect('/02_query/')
from django.shortcuts import redirect
def query_views(request):
authors = Author.objects.filter(isActive=True)
return render(request,'query.html',locals())
def delete_views(request,id):
author = Author.objects.get(id=id)
author.isActive=False
author.save()
#重定向,参数是要重定向的地址
return redirect('/02_query/')
from django.shortcuts import reverse
def query_views(request):
authors = Author.objects.filter(isActive=True)
return render(request,'query.html',locals())
def delete_views(request,id):
author = Author.objects.get(id=id)
author.isActive=False
author.save()
#方向解析,参数是url的别名
url = reverse('query')
#重定向,参数是要重定向的地址
return redirect(url)
1、使用后台管理Models
后台登录地址:http://localhost:8000/admin
1、创建后台管理员
./manage.py createsuperuser
Username:
Email Address:可以为空
Password:
Password(agin)
2、基本管理
1、在应用中的admin.py中注册要管理的数据
1、admin.py
作用:注册需要管理的Models,只有在此注册的Model才允许被管理,否则无法管理
2、注册Model
from .models import *
admin.site.register(Entry)
3、修改models.py处理显示内容
后台默认效果可读性不高
def __str__(self):
return self.name//将后台显示Author object(一条记录),修改为该对象的name属性值
在实体类中属性添加verbose_name="姓名"
name = models.CharField(max_length=30,verbose_name="姓名")//显示name字段为姓名
name = models.CharField(max_length=30,verbose_name="aa")//显示name字段为Aa
4、通过内部类Meta实现展现的属性
允许为每个model类设置内部类Meta来设置其展示形式
class Author(models.Model):
….
….
class Meta:
1、db_table:指定该实体类对应到表的名称,该操作必须先同步到数据库
2、verbose_name:定义该实体类在admin中显示的名字(复数形式),会在该属性值的后面加s
3、verbose_name_plural:效果同上,是单数形式
4、ordering:在后台显示数据时的排序规则,取值是一个列表,默认是升序,降序在字段前面加‘-’
ordering = ["uphone"]:按照电话号码升序
ordering = ["-uphone"]:按照电话号码降序
5、ImageField数据类型
在示例对象中添加该数据类型
1、pip install Pillow
2、picture = models.ImageField(
null=True,upload_to='static/upload/usrimg',verbose_name='头像')
null = True:因为数据表中原先有数据,现在添加新字段,需要允许为空
upload_to:表示上传后在项目中的保存路径
verbose_name:在后台显示的名字
2、高级管理
1、在admin.py中创建管理类,实现高级管理功能
1、定义EntryAdmin类,继承自admin.ModelAdmin
2、注册实体类
class AuthorAdmin(admin.ModelAdmin):
pass
admin.site.register(Author, AuthorAdmin)
3、允许在EntryAdmin增加的属性
1、list_display
作用:在显示实体信息的页面上,都显示哪些字段
取值:列表 或 元组
2、list_display_links
作用:定义能够链接到具体实体页面的链接们
取值:由属性名组成的元组或列表
注意:取值必须要出现在list_display中,默认为list_display的第一个字段,
3、list_editable
作用:定义在列表页面中允许被修改的字段
取值:由属性名组成的元组或列表
注意:list_editable中的值不能出现在list_display_links
4、search_fields
作用:添加允许被搜索的字段
取值:由属性组成的元组或列表
5、list_filter
作用:在列表的右侧增加过滤器,实现快速筛选
取值:由属性组成的元组或列表
6、date_hierarchy
作用:在顶部增加一个时间选择器,所以取值必须是DateField 或 DateTieField的列
7、fields
作用:在实体的详细页面中,显示哪些属性,并按照什么样的顺序显示
取值:由属性组成的元组或列表,空列表或元组无效
8、fieldsets
作用:在实体的详细页面中,对属性进行分组
注意:fieldsets 与 fields不能共存
语法:
fieldsets = (
#分组1
(‘当前分组的名称’,{'fields':(属性1,属性2…),‘classes’:(‘collapse’)}),
#分组2
(‘当前分组的名称’,{'fields':(属性1,属性2…),‘classes’:(‘collapse’)}),
……
)
‘classes’:(‘collapse’):表示可以被折叠
9、filter_horizontal(“必须是具有多对多关系的属性”)和 filter_vertical(“必须是具有多对多关系的属性”)
注意:
当两个属性与raw_id_fields共存时,效果将会失效
原图:
filter_horizontal = ('publisher',):
filter_vertical = ("publisher",)
10、raw_id_fields("必须是具有一对多或多对多关系的属性")
class BookAdmin(admin.ModelAdmin):
list_display = ('title','publication_date')
#book与publisher是多对一的关系,
#book域author是多对多的关系
raw_id_fields = ('publisher','author')
filter_horizontal = ('author',)#此处域raw_id_fields("author")共存将失效
原图:
aaarticlea/png;base64,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" alt="" />
raw_id_fields = ('publisher','author'):
aaarticlea/png;base64,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" alt="" />
2、Django连接查询(关系映射)
1、一对一映射(1:1)
1、什么是一对一
A表中的一条记录只能与B表中的一条记录匹配关联
B表中的一条记录也只能与A表中的一条记录相关联
数据库中的实现:
A表:设计主键
B表:有主键,增加一列(作为外键),并应用A表中的主键值,还得增加一个唯一约束
2、语法:
在关联的两个类的任何一个类中,增加对另外一个类的应用
属性 = models.OneToOneField(Author,null=True)
author = models.OneToOneField(Author,null=True)
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
| age | int(11) | NO | | NULL | |
| author_id | int(11) | YES | UNI | NULL | |
+-----------+-------------+------+-----+---------+----------------+
| wife | CREATE TABLE `wife` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(30) NOT NULL,
`age` int(11) NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `author_id` (`author_id`),
CONSTRAINT `wife_author_id_1672739f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
#编写Wife实体了类,与Author做一对一关系映射
class Wife(models.Model):
name = models.CharField(max_length=30,verbose_name="姓名")
age = models.IntegerField(verbose_name='年龄')
#指定一对一的关联关系,引用自Author实体
author = models.OneToOneField(Author,verbose_name='丈夫')
class Meta:
db_table='wife'
3、查询
class Wife(models.Model):
name = models.CharField(max_length=30,verbose_name='姓名')
age = models.IntegerField(verbose_name="年龄")
#增加一对一的关系映射
author = models.OneToOneField(Author,null=True,verbose_name='丈夫')
正向查询:通过wife 找 author
#获取id为1的wife的信息
w = Wife.objects.get(id=1)
#在获取wife关联的author
a = w.author
def oto_views(requset):
#先获取i的为1的wife的信息
wife = Wife.objects.get(id=1)
#再获取对应的author
author = wife.author
return render(requset,'03_oto.html',locals())
反向查询:通过author 找 wife
a = Author.objects.get(id=1)
w = a.wife
wife 是由Django通过OneToOneField在Author中默认增加的一个属性,在数据库中没有体现
2、一对多映射
1、什么是一对多
A表中的一条数据可以与B表中的任意多条数据匹配
B表中的一条数据只能与A表中的一条数据相关联
2、语法:
在‘多’表中增加外键,对‘一’表表中的主键进行引用
使用外键(Foreign Key)
在‘多’实体中增加:
属性 = models.ForeignKey(实体类)
pub = models.ForeignKey(Publisher,null=True)
+----+----------+------------------+--------+
| id | title | publication_date | pub_id |
+----+----------+------------------+--------+
| 1 | Python | 1990-01-20 | 1 |
| 2 | HTML/CSS | 1992-12-18 | NULL |
| 3 | Django | 2018-08-18 | 3 |
| 4 | HTML/CSS | 1992-02-18 | 2 |
| 5 | JAVA | 2018-08-19 | 3 |
+----+----------+------------------+--------+
| book | CREATE TABLE `book` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(30) NOT NULL,
`publication_date` date NOT NULL,
`publisher_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `book_publisher_id_ac4b162a_fk_publisher_id` (`publisher_id`),#普通索引
CONSTRAINT `book_publisher_id_ac4b162a_fk_publisher_id` FOREIGN KEY (`publisher_id`) REFERENCES `publisher` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
3、查询
Book(M)和publisher(1)
class Book(models.Model):
#增加一对多的关系
pub = models.ForeignKey(Publisher,null=True,verbose_name="出版社")
1、正向查询 —— 通过Book 查询 Publisher
book = Book.objects.get(id=1)
publisher = book.pub
def otm_views(request):
#先查询id为1的book的信息
book = Book.objects.get(id=1)
#在查询book关联publisher
publisher=book.publisher
return render(request,'04_otm.html',locals())
2、反向查询 - 通过Publisher 查询 Book
Django会通过ForeignKey()向关联的类中增加一个隐式属性:当前类_set,(当前类小写)
p = Publisher.objects.get(id=1)
bookset = p.book_set.all()//book_set是Django在Publisher实体类中添加book_set属性
3、多对多映射
1、什么是多对多
A表中的一条记录可以与B表中的任意多条记录相关联
B表中的一条记录可以与A表中的任意多条记录相关联
2、在数据库中的体现
必须创建第三张表,用于关联涉及到的两张表的数据
3、语法:
在涉及的到两个类中的任意一个类中,都可以对另外一个类的多对多的引用
entry=models.ManyToManyField(Entry)
示例:
创建书籍与作者之间的多对多的引用
可以在书籍实体类中,增加对作者的引用
可以在作者实体类中,增加对书籍的引用
class Book(models.Model):
……..
author=models.ManyToManyField(Author)
+-----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| book_id | int(11) | NO | MUL | NULL | |
| author_id | int(11) | NO | MUL | NULL | |
+-----------+---------+------+-----+---------+----------------+
| book_author | CREATE TABLE `book_author` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`book_id` int(11) NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `book_author_book_id_author_id_4fda6750_uniq` (`book_id`,`author_id`),#复合唯一索引book_id和author_id不能同时相同
KEY `book_author_author_id_325bf96f_fk_author_id` (`author_id`),#普通索引
CONSTRAINT `book_author_author_id_325bf96f_fk_author_id` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`),
CONSTRAINT `book_author_book_id_19a45511_fk_book_id` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
4、查询
class Book(models.Model):
……..
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.objects.get(id=2)
#再查询对应的所有的书籍
bookList = author.book_set.all()
def mtm_views(request):
#正向查询
book =Book.objects.get(id=2)
authors = book.author.all()
#反向查询,book_set
author = Author.objects.get(id=3)
bookList = author.book_set.all()
return render(request,'05_mtm.html',locals())
HTTP通信协议
1、什么是HTTP
HTTP:Hyper Text Transfer Protocol(超文本传输协议)
作用:规范了数据是如何打包以及传送的
2、请求消息
由请求起始行,请求消息头,请求主体
请求主题:
post和put两种提交方式会产生请求主体
3、响应消息
由响应起始行,响应消息头,响应主体
1、HttpRequest
1、HttpRequest介绍
HttpRequest,在Django中是对请求对象的封装体现,会封装请求过程中所有的信息,
在Django中,HTTPRequest被封装成了Request被自动传到了视图处理函数中
以双下划线或单下划线开头的不是HTTPRequest协议中的属性或方法,是Django自动添加的
['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']
2、HTTPRequest中的主要内容
1、request.scheme:请求协议
2、request.body:请求主题(只有post和put请求方式时才会有请求主题)
3、request.path:请求路径
4、request.get_host():请求的主机地址或域名
5、request.method:获取请求方法
6、request.GET:封装了GET请求方式提交的数据
7、request.POST:封装了POST请求方式提交的数据
说明:
GET,POST的返回值都是一个字典,字典的值是一个列表,但是通过request.GET['key']取出的一个字符串,(为什么?)
答案:Django中通过重写__getitem__方法实现的
'''
QueryDict.__getitem__(key)
返回给出的 key 的值。如果key 具有多个值,__getitem__()
返回最后(最新)的值。如果 key 不存在,
则引发django.utils.datastructures.MultiValueDictKeyError。(
它是Python 标准KeyError 的一个子类,所以你仍然可以坚持捕获KeyError。)
总结:Django中通过重写__getitem__方法实现的
'''
class MyDict():
def __init__(self,iterable):
self.data = iterable
def \_\_getitem\_\_(self, item):
return self.data\[item\]\[-1\]
dict = {
'name':['xdl','gj'],
'age':[25]
}
myDict = MyDict(dict)
print(type(myDict))#
print(myDict['name'])#gj
8、request.COOKIES:封装了cookie的数据
9、request.META:封装了请求的元数据
request.META["HTTP_REFERER"]:封装了请求的源地址
def requset_views(request):
#request,类型就是HTTPRequest
#request,封装的是所有与请求相关的内容
#print(dir(request))
#请求协议(方案),http
scheme = request.scheme
#请求主体
body = request.body
#请求资源的具体路径,根相对路径,/01\_requset/
path = request.path
#请求的主机地址或域名,127.0.0.1:8000
host = request.get\_host()
#请求方式,GET
method = request.method
#get方式请求的数据,得到的是一个字典,<QueryDict: {}>
get = request.GET
#post方式请求数据,<QueryDict: {}>
post = request.POST
#cookie中的数据,返回的是一个字典
# {'csrftoken': 'w1TDCKqZakTz9IKn94luPeFjefTsGdDnRqGxzXdGJ5yNOQaWfeJC5MbUw0KRPWzo',
# 'sessionid': '702s33knczrluqmeh15m9rvbasptd39i'}
cookies = request.COOKIES
#请求元数据,返回的是一个字典
meta = request.META
return render(request,'01\_request.html',locals())
3、获取请求提交的数据
1、get请求方式
request.GET["名称"]
1、使用表单提交数据
解决方案:
1、取消CSRF的验证
删除settings.py中MIDDLEWARE中的'CsrfViewMiddleware'中间件
2、开放验证权限,无需验证,直接进入
在视图处理函数之上增加一个装饰器@crsf_protect
需要引包:from django.views.decorators.csrf import csrf_protect
3、必须要通过验证后才可以请求
在模板中
def register_views(request):
if request.method =="GET":
form = RegisterForm()
return render(request,'06_register.html',locals())
else:
form = RegisterForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
try:
User.objects.get(uname=cd['uname'])
return HttpResponse('用户名已存在')
except ObjectDoesNotExist:
User.objects.create(**cd)
return HttpResponse("注册成功")
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文本",
………
}
#创建class表示登录的表单,要关联Users实体类
class UserLoginForm(forms.ModelForm):
class Meta:
#指定关联的model
model = User
#指定要生成的控件字段
fields = ["uname","upwd"]
#指定每个控件对应的label
labels={
"uname":"用户名",
"upwd":"密码",
}
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:
9、Select:
3、小部件的使用
1、继承自forms.Form
1、基本版
只指定控件的类型
属性=forms.CharField(
lable="标签",
widget=forms.小部件的类型
)
示例:
upwd=forms.CharField(label=“密码”,widget=forms.PasswordInput)
2、高级版
指定控件类型之外还允许设置html属性
属性=forms.CharField(
label="标签",
widget=forms.小部件类型(
attrs = {
"html属性名":"属性值",
"html属性名":"属性值",
……
}
)
)
class WidgetForm(forms.Form):
uname = forms.CharField(
label="用户名称",
widget=forms.TextInput(
attrs={
'name':'user_name',
'placeholder':"请输入用户名称",
'class':'form-control',
}
)
)
upwd = forms.CharField(
label="用户密码",
widget=forms.PasswordInput(
attrs={
'name':'user_pwd',
'placeholder':'请输入密码',
'class':'form-control',
}
)
)
2、继承自forms.ModelForm
class Widget2Form(forms.ModelForm):
class Meta:
model = User
fields= "__all__"
labels={
"属性1":"标签1",
"属性2":"标签2",
….
}
widgets={
"属性1":forms.小部件类型(attrs={}),
"属性2":forms.小部件类型(attrs={}),
……..
}
class Widget2Form(forms.ModelForm):
class Meta:
model=User
fields=("uname","upwd")
labels={
"uname":'用户名称',
"upwd":"用户密码",
}
widgets={
'uname':forms.TextInput(
attrs={
"placeholder":'请输入用户名'
}
),
'upwd':forms.PasswordInput(
attrs={
'placeholder':"请输入密码"
}
)
}
2、cookies
1、什么是cookies
cookies是一种数据的存储技术,只能保存字符串
允许将一段文本保存在客户端上(浏览器)的一种技术,并可以长时间保存
2、cookies的使用场合
1、记住密码
2、保存搜索关键词
3、在Django中使用cookies
1、设置cookies的值(将数据保存客户端)
语法:
响应对象.set_cookie(key,value,[expires])
key:cookie的名字
value:cookie的值
expires:保存时间,以s为单位,如果不给该参数,则浏览器关闭,cookie失效
示例:
响应对象.set_cookie('uname','xdl',60*60*24*366)
响应对象:HttpResponse,render,HttpResponseRedirect,redirect
1、不使用模板(HttpResponse)
resp = HttpResponse("给客户端的一句话")
resp.set_cookie('key','value',expires)
return resp
2、使用模板(render)
resp = render(reuqest,'xxx.html',locals())
resp.set_cookie('key','value',expires)
return resp
3、重定向(HttpResponseRedirect/redirect)
resp = HttpResponseRedirect('/地址/')
resp.set_cookie('key','value',expires)
return resp
2、获取cookies的值(将数据从客户端中获取出来)
通过request.COOKITES(返回的是一个字典,通过键值可以取值)
获取当前访问站点下所有的cookies的信息
3、删除cookie
响应对象.delete_cookie('key')
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、在setting.py中,有关session的设置
1、SESSION_COOKIE_AGE
作用:设置sessionID在cookies中的保存时长,默认为15天
示例:
SESSION_COOKIE_AGE=60*6024
2、SESSION_EXPIRE_AT_BROWSER_CLOSE(建议使用)
作用:设置关闭浏览器时清除服务器上对象的session空间
示例:
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
cookie 存取中文
def setCookie_views(request):
uname = '张三丰'
#将uname转化为unicode
uname = json.dumps(uname)
resp = HttpResponse('set cookie ok')
resp.set_cookie('name',uname)
return resp
def getCookie_views(requset):
uname = requset.COOKIES['name']
#将unicode码转换为中文
uname = json.loads(uname)
return HttpResponse(uname)
上传图片
前段页面:
上传图片
访问图片:通过views函数返回这个对象集合,然后在前端循环获取图片路径.url
{% for show in p %}
{% if show.pic %}
{% endif %}
{% endfor %}
后端配置:
配置settings文件
MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace('\\','/')
MEDIA_URL = '/media/'
配置urls文件,主路由文件
from django.conf.urls import url, include
from django.contrib import admin
from sale import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.index,name='index'),
url(r'^userinfo/',include('userinfo.urls')),
]+ static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
views.py视图
def salecar(request):
new_a = Aid()#实体类
pic = request.FILES.get('pic')
new_a.pic = pic
new_a.save()
return render(request,'infomessage.html')
手机扫一扫
移动阅读更方便
你可能感兴趣的文章