Python|Python Web框架——Django

返回顶部
使用框架简单快速开发特定的系统。

pip freeze > requirements.txt


pip install -r requirements.txt

一 MVC和MTV模式

二 简介
Django时有Python开发的一个免费的开源网站框架,可以用于快速搭建高性能、优雅的网站。
Django框架的特点:
  • 强大的数据库功能
  • 自带强大的后台功能
  • 通过正则匹配随意定义的网址
  • 强大易扩展的模板系统
  • 缓存系统
  • 国际化
三 Django安装方式
1.利用pip安装Django。
oliver@oliver-G460:~$ sudo pip3 install Django

2.利用源码包安装Django。
oliver@oliver-G460:~$ tar -zxvf django-1.10.xx.tar.gz

解压后进入目录,执行:
python3 setup.py install

3.利用Linux自带源安装Django。
sudo apt-get install python3-django


检查Django是否安装成功:
oliver@oliver-G460:~$ python3 Python 3.5.2 (default, Sep 10 2016, 08:21:44) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import django >>> django.VERSION (1, 10, 2, 'final', 0)


如果希望安装不同版本的Django环境,则需要通过virtualenv来管理多个开发环境。
四 Django项目创建
方式一:用命令创建项目和app
1. 创建一个新的Django项目
Python|Python Web框架——Django
文章图片

2. 创建app
python3 manage.py startapp app-name 或 django-admin.py startapp app-name Python|Python Web框架——Django
文章图片

需要注意的是,通过命令行创建的项目,在settings.py中,如app名称和模板路径及templates目录等信息要自己添加。
方式二:用Pycharm创建
在File→New Project中选择Django,输入项目名称mysite和应用名称myApp,完成创建。
Python|Python Web框架——Django
文章图片

创建完成后, 用Pycharm打开项目,查看项目和app目录文件
Python|Python Web框架——Django
文章图片

  • manage.py:用于管理Django站点。
  • settings.py:项目所有的配置信息,包含项目默认设置,数据库信息,调试标识以及其它工作变量等。
  • urls.py:负责把URL映射到视图函数,即路由系统。
  • wsgi.py:内置runserver命令的WSGI应用配置。
五 Django urls(路由系统)
即urls.py文件。其本质是建立url与其所调用的视图函数的映射关系,以此来规定访问什么网址去对应什么内容,执行哪个视图函数。
Python|Python Web框架——Django
文章图片

urlpatterns = [ url(正则表达式,views视图函数,[参数],[别名]), ]

说明(括号中四部分的意义):
  • 正则表达式字符串来匹配浏览器发送到服务端的URL网址
  • 可调用的视图函数对象。先引入(import)再使用
  • 要传给视图函数的默认参数(字典形式)
  • name,即别名。HTML中form表单参数action属性值使用此别名后,即便url发生变化,也无需在HTML中批量进行修改。
1 URL配置举例: Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
from django.conf.urls import url from django.contrib import adminfrom app01 import viewsurlpatterns = [url(r'^articles/2003/$', views.special_case_2003),#url(r'^articles/[0-9]{4}/$', views.year_archive),url(r'^articles/([0-9]{4})/$', views.year_archive),#no_named groupurl(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),]

View Code 用()括起来表示保存为一个子组,每个子组作为一个参数(无名参数),被views.py中的对应函数接收。参数个数与视图函数中的形参个数要保持一致。

(注意:当匹配到第一个url后立即返回,不再向下查找匹配。)
2 带命名的组Named group(?P<>)用法 ?P<group_name> 表示带命名的参数,例如:将year='2016'作为一个整体传个视图函数。此处的组名称必须与视图函数中的形参名称一致。由于有参数名称与之对应,所以视图函数有多个形参时,不需要考虑参数的先后顺序。
from django.conf.urls import urlfrom . import viewsurlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/(?P[0-9]{4})/$', views.year_archive),# year=2016 url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive), url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[0-9]{2})/$', views.article_detail), ]

3 默认参数(可选) 如下所示,如果请求地址为/blog/2016,表示将year='2016',foo='bar'传给视图函数,视图函数中必须有相同名称的形参来接收值。
from django.conf.urls import url from . import viewsurlpatterns = [ url(r'^blog/(?P[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), ]

4 name别名(可选) 固定用法:
url(r'^/index/',views.index,name='bieming')
如果url中的路径修改为/index2/,对应的模板,甚至还视图中的跳转,以及 models.py 中也可能有获取网址的地方。每个地方都要改,修改的代价很大,一不小心,有的地方没改过来,那个就不能用了。
因此,在需要跳转或获取网址的地方,使用别名设置的名称,以后便可以随意修改url了。
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
urlpatterns = [ url(r'^index',views.index,name='bieming'), url(r'^admin/', admin.site.urls), # url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive), # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),] ###################def index(req): if req.method=='POST': username=req.POST.get('username') password=req.POST.get('password') if username=='alex' and password=='123': return HttpResponse("登陆成功")return render(req,'index.html')##################### Title - 锐客网 {#
#} 用户名: 密码:
#######################

View Code 5 URLconf 一个网站包含成千上万个URL,如果所有的URL映射都放在一个文件下,很可能会出错,也不便与维护。
因此,我们在每个app应用下分别创建一个urls目录,将不同的请求分发给不同app下的urls去匹配,如:对于/blog/index/请求直接交给‘blog.urls’去处理,清晰明确,更方便管理。
Python|Python Web框架——Django
文章图片


六 Django views(视图函数)
http请求中产生的两大核心对象:
http请求:HttpRequest对象
http响应:HttpResponse对象
所在位置:django.http
request就是指HttpRequest。
1 HttpRequest对象的属性和方法
属性 描述
path 请求页面的全路径,不包括域名—例如, "/music/bands/the_beatles/"。
method 请求中使用的HTTP方法的字符串表示。全大写表示。
GET 包含所有HTTP GET参数的类字典对象
POST 包含所有HTTP POST参数的类字典对象
REQUEST 为了方便,该属性是POST和GET属性的集合体,但是有特殊性,先查找POST属性,然后再查找GET属性
COOKIES 包含所有cookies的标准Python字典对象。Keys和values都是字符串。
FILES 包含所有上传文件的类字典对象。FILES中的每个Key都是标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys:(Filename: 上传文件名,用Python字符串表示; content-type: 上传文件的Content type; content: 上传文件的原始内容)注意:只有在请求方法是POST,并且请求页面中
enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。
META 包含所有可用HTTP头部信息的字典,例如:(CONTENT_LENGTH,CONTENT_TYPE,QUERY_STRING: 未解析的原始查询字符,串,REMOTE_ADDR: 客户端IP地址REMOTE_HOST: 客户端主机名,SERVER_NAME: 服务器主机名,SERVER_PORT: 服务器端口); META 中这些头加上前缀HTTP_最为Key, 例如:(HTTP_ACCEPT_ENCODING,HTTP_ACCEPT_LANGUAGE,HTTP_HOST: 客户发送的HTTP主机头信息,HTTP_REFERER: referring页,HTTP_USER_AGENT: 客户端的user-agent字符串,HTTP_X_BENDER: X-Bender头信息)
user 是一个django.contrib.auth.models.User 对象,代表当前登录的用户。如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。见例子1
session 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。
raw_post_data 原始HTTP POST数据,未解析过。 高级处理时会有用处。

method 描述
__getitem__(key) 返回GET/POST的键值,先取POST,后取GET。如果键不存在抛出 KeyError。这是我们可以使用字典语法访问HttpRequest对象。例如:request["foo"]等同于先request.POST["foo"] 然后 request.GET["foo"]的操作。
has_key() 检查request.GET or request.POST中是否包含参数指定的Key。
get_full_path() 返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true"
is_secure() 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。
get_full_path(),比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123 req.path得到的结果是:/index33

2 HttpResponse对象的属性和方法 对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
HttpResponse类在django.http.HttpResponse
在HttpResponse对象上扩展的常用方法:
页面渲染:render()(推荐)或render_to_response(), 页面跳转:redirect("路径") locals():可以直接将函数中所有的变量传给模板

七 Django templates(模板)
模板由HTML+逻辑控制代码组成。
1 变量 使用双大括号来引用变量
语法格式:{{var_name}}

2 Template和Context对象 渲染操作流程:
一旦创建Template对象之后,可以用context传递数据给它,它是一系列变量和它们值的集合,模板使用它来赋值模板变量标签和执行块标签
context在django里表现为Context类,在django.template模块中
Context类构造是一个可选参数:一个字典映射变量和它们的值
创建一系列Context对象之后,调用Template对象的render()方法并传递Context对象来填充模板
同一个模板渲染多个context:
1 >>>from django,template import Template,Context 2 >>>t=Template("My name is {{name}},I love{{language}}") 3 >>>c=Context({'name':'BeginMan','language':'Python/Js/C#'}) 4 >>>t.render(c) 5 --------------------------------output---------------------------------------------- 6 My name is BeginMan ,I love Python/Js/C#


推荐写法:
def current_time(req):now=datetime.datetime.now()return render(req, 'current_datetime.html', {'current_date':now})# 字典部分指定就是Context对象,render()方法将Context对象的键值传递给模板,并填充模板。

3 深度变量查找 context不仅能传递简单的参数(字符串),也可以传递列表和字典对象。
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 #最好是用几个例子来说明一下。 2 # 首先,句点可用于访问列表索引,例如: 3 4 >>> from django.template import Template, Context 5 >>> t = Template('Item 2 is {{ items.2 }}.') 6 >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) 7 >>> t.render(c) 8 'Item 2 is carrots.' 9 10 #假设你要向模板传递一个 Python 字典。 要通过字典键访问该字典的值,可使用一个句点: 11 >>> from django.template import Template, Context 12 >>> person = {'name': 'Sally', 'age': '43'} 13 >>> t = Template('{{ person.name }} is {{ person.age }} years old.') 14 >>> c = Context({'person': person}) 15 >>> t.render(c) 16 'Sally is 43 years old.' 17 18 #同样,也可以通过句点来访问对象的属性。 比方说, Python 的 datetime.date 对象有 19 #year 、 month 和 day 几个属性,你同样可以在模板中使用句点来访问这些属性: 20 21 >>> from django.template import Template, Context 22 >>> import datetime 23 >>> d = datetime.date(1993, 5, 2) 24 >>> d.year 25 >>> d.month 26 >>> d.day 27 >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') 28 >>> c = Context({'date': d}) 29 >>> t.render(c) 30 'The month is 5 and the year is 1993.' 31 32 # 这个例子使用了一个自定义的类,演示了通过实例变量加一点(dots)来访问它的属性,这个方法适 33 # 用于任意的对象。 34 >>> from django.template import Template, Context 35 >>> class Person(object): 36 ...def __init__(self, first_name, last_name): 37 ...self.first_name, self.last_name = first_name, last_name 38 >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') 39 >>> c = Context({'person': Person('John', 'Smith')}) 40 >>> t.render(c) 41 'Hello, John Smith.' 42 43 # 点语法也可以用来引用对象的方法。 例如,每个 Python 字符串都有 upper() 和 isdigit() 44 # 方法,你在模板中可以使用同样的句点语法来调用它们: 45 >>> from django.template import Template, Context 46 >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') 47 >>> t.render(Context({'var': 'hello'})) 48 'hello -- HELLO -- False' 49 >>> t.render(Context({'var': '123'})) 50 '123 -- 123 -- True' 51 52 # 注意这里调用方法时并* 没有* 使用圆括号 而且也无法给该方法传递参数;你只能调用不需参数的 53 # 方法。

View Code 4 变量过滤器filter
语法格式:{{obj|filter:param}}

Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 # 1add:给变量加上相应的值 2# 3# 2addslashes:给变量中的引号前加上斜线 4# 5# 3capfirst:首字母大写 6# 7# 4cut:从字符串中移除指定的字符 8# 9# 5date:格式化日期字符串 10# 11# 6default:如果值是False,就替换成设置的默认值,否则就是用本来的值 12# 13# 7default_if_none:如果值是None,就替换成设置的默认值,否则就使用本来的值 14 15 16 #实例: 17 18 #value1="aBcDe" 19 {{ value1|upper }} 20 21 #value2=5 22 {{ value2|add:3 }} 23 24 #value3='hello wo r ld' 25 {{ value3|cut:' ' }} 26 27 #import datetime 28 #value4=datetime.datetime.now() 29 {{ value4|date:'Y-m-d' }} 30 31 #value5=[] 32 {{ value5|default:'空的' }} 33 34 #value6='跳转' 35 36 {{ value6 }} 37 38 {% autoescape off %} 39{{ value6 }} 40 {% endautoescape %} 41 42 {{ value6|safe }} 43 44 {{ value6|striptags }} 45 46 #value7='1234' 47 {{ value7|filesizeformat }} 48 {{ value7|first }} 49 {{ value7|length }} 50 {{ value7|slice:":-1" }} 51 52 #value8='http://www.baidu.com/?a=1&b=3' 53 {{ value8|urlencode }} 54value9='hello I am yuan'

View Code 5 常用标签(tag)
语法格式:{% tags %}

(1){% if %}

(2){% for %}

(3){% csrf_token %}

(4){% url %} :引用路由配置的地址

(5){% with %} :用简短的变量名代替复杂的变量名

(6){% verbatim %} :禁止render

(7){% load %} :加载标签库

6 自定义filter和simple_tag (1)在app下创建templatetags目录或模块,目录名称必须这样写。
Python|Python Web框架——Django
文章图片

(2)创建.py文件,如my_tags。(其中,register名称不可改变)
Python|Python Web框架——Django
文章图片

(3)在使用自定义filter和simple_tag的html文件之前,通过 {% load my_tags %}导入前面自己创建的my_tags标签库。(注意:settings中INSTALLED_APPS中必须添加当前的app名称,否则找不到自定义的tags)
(4)调用自定义的filter和simple_tag。
Python|Python Web框架——Django
文章图片


filter可以用在if等语句后,simple_tag不可以:
{% if num|filter_multi:30 > 100 %} {{ num|filter_multi:30 }} {% endif %}

7 extend模板继承 将shopping_car.html和ordered.html中大量重复的代码提取出来,写入base.html中,不同的部分分别写在各自模板中,通过extends继承base.html中的公共部分。
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 2 3 4 5Title - 锐客网 6 37 38 39
40 44
45{% block content %} 46{% endblock %} 47
48 49

base.html shopping_car.html:
1 {% extends 'base.html' %} 2 3 4 {% block content %} 5购物车 6 {% endblock %}

ordered.html:
1 {% extends 'base.html' %} 2 3 4 {% block content %} 5订单 6 {% endblock %}


八 Django modules(模型)
1django默认支持sqlite,mysql, oracle,postgresql数据库。
<1> sqlite
django默认使用sqlite的数据库,默认自带sqlite的数据库驱动
引擎名称:django.db.backends.sqlite3
<2> mysql
引擎名称:django.db.backends.mysql
2mysql驱动程序
MySQLdb(mysql python)
mysqlclient
MySQL
PyMySQL(纯python的mysql驱动程序)
3Django的项目中默认使用sqlite数据库,在settings中设置如下:
Python|Python Web框架——Django
文章图片

如果想要使用mysql数据库,只需要做如下更改:
Python|Python Web框架——Django
文章图片

注意:NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
USER和PASSWORD分别是数据库的用户名和密码。
设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
然后,启动项目,会报错:no module named MySQLdb
这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
所以,我们只需要找到项目名文件下的__init__,在里面写入:
Python|Python Web框架——Django
文章图片

ORM(对象关系映射) 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的。面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数据库是企业级应用环境中永久存放数据的主流数据存储系统。对象和关系数据是业务实体的两种表现形式,业务实体在内存中表现为对象,在数据库中表现为关系数据。内存中的对象之间存在关联和继承关系,而在数据库中,关系数据无法直接表达多对多关联和继承关系。因此,对象-关系映射(ORM)系统一般以中间件的形式存在,主要实现程序对象到关系数据库数据的映射。面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。如果打开你最近的程序,看看DAL代码,你肯定会看到很多近似的通用的模式。我们以保存对象的方法为例,你传入一个对象,为SqlCommand对象添加SqlParameter,把所有属性和对象对应,设置SqlCommand的CommandText属性为存储过程,然后运行SqlCommand。对于每个对象都要重复的写这些代码。除此之外,还有更好的办法吗?有,引入一个O/R Mapping。实质上,一个O/R Mapping会为你生成DAL。与其自己写DAL代码,不如用O/R Mapping。你用O/R Mapping保存,删除,读取对象,O/R Mapping负责生成SQL,你只需要关心对象就好。对象关系映射成功运用在不同的面向对象持久层产品中,如:Torque,OJB,hibernate,TopLink,Castor JDO, TJDO 等。
一般的ORM包括以下四部分:一个对持久类对象进行CRUD操作的API;一个语言或API用来规定与类和类属性相关的查询;一个规定mapping metadata的工具;一种技术可以让ORM的实现同事务对象一起进行dirty checking, lazy association fetching以及其他的优化操作。
1django ORM——创建表(模型)
django模型常用的字段类型
字段名 参数
意义
AutoField

一个能够根据可用ID自增的 IntegerField
BooleanField

一个真/假(true/false)字段
CharField
(max_length)
一个字符串字段,适用于中小长度的字符串。对于长段的文字,请使用 TextField
CommaSeparatedIntegerField
(max_length)
一个用逗号分隔开的整数字段
DateField
([auto_now],[auto_now_add])
日期字段
DateTimeField

时间日期字段,接受跟 DateField 一样的额外选项
EmailField

一个能检查值是否是有效的电子邮件地址的 CharField
FileField
(upload_to)
一个文件上传字段
FilePathField
(path,[match],[recursive])
一个拥有若干可选项的字段,选项被限定为文件系统中某个目录下的文件名
FloatField
(max_digits,decimal_places)
一个浮点数,对应Python中的 float 实例
ImageField
(upload_to,[height_field] ,[width_field])
像 FileField 一样,只不过要验证上传的对象是一个有效的图片。
IntegerField

一个整数。
IPAddressField

一个IP地址,以字符串格式表示(例如: "24.124.1.30" )。
NullBooleanField

就像一个BooleanField ,但它支持 None /Null 。
PhoneNumberField

它是一个CharField ,并且会检查值是否是一个合法的美式电话格式
PositiveIntegerField

和IntegerField 类似,但必须是正值。
PositiveSmallIntegerField

与PositiveIntegerField 类似,但只允许小于一定值的值,最大值取决于数据库.
SlugField

嵌条 就是一段内容的简短标签,这段内容只能包含字母、数字、下
划线或连字符。通常用于URL中
SmallIntegerField

和IntegerField 类似,但是只允许在一个数据库相关的范围内的数值(通常是-32,768到
+32,767)
TextField

一个不限长度的文字字段
TimeField

时分秒的时间显示。它接受的可指定参数与 DateField 和 DateTimeField 相同。
URLField

用来存储URL的字段。
USStateField

美国州名称缩写,两个字母。
XMLField
(schema_path)
它就是一个TextField ,只不过要检查值是匹配指定schema的合法XML。

参数名 意义
null
如果设置为 True 的话,Django将在数据库中存储空值为 NULL 。默认为 False 。
blank
如果是 True ,该字段允许留空,默认为 False 。
choices
一个包含双元素元组的可迭代的对象,用于给字段提供选项。
db_column
当前字段在数据库中对应的列的名字。
db_index
如果为 True ,Django会在创建表格(比如运行 manage.py syncdb )时对这一列创建数据库索引。
default
字段的默认值
editable
如果为 False ,这个字段在管理界面或表单里将不能编辑。默认为 True 。
help_text
在管理界面表单对象里显示在字段下面的额外帮助文本。
primary_key
如果为 True ,这个字段就会成为模型的主键。
radio_admin
默认地,对于ForeignKey 或者拥有 choices设置的字段,Django管理界面会使用列表选择框()。如果 radio_admin 设置为 True 的话,Django就会使用单选按钮界面。
unique
如果是 True ,这个字段的值在整个表中必须是唯一的。
unique_for_date
把它的值设成一个DataField 或者DateTimeField 的字段的名称,可以确保字段在这个日期内不会出现重复值。
unique_for_month
和unique_for_date 类似,只是要求字段在指定字段的月份内唯一。
unique_for_year
和unique_for_date 及 unique_for_month 类似,只是时间范围变成了一年。
verbose_name
除 ForeignKey、ManyToManyField 和 OneToOneField 之外的字段都接受一个详细名称作为第一个位置参数。

实例:创建一个书籍、作者、出版社数据库结构
一本书可能有多个作者,一个作者可以写多本书,一本书通常仅由一个出版社出版。因此作者与书为多对多关系,出版社与书为一对多关系。接下来,我们来创建表(模型)。
多对多关系(many-to-many):彼此一对多,自动创建第三张表来表示对应关系。
一对多关系(one-to-many):主外键关系,在many对应的表中给需要的字段添加外键。
一对一(one-to-one):在一对多基础上,在多的哪个表ForeignKey的基础上加unique=true。
1每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。
2每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)。
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 from django.db import models 2 3 # Create your models here. 4 class Publisher(models.Model): 5 6name = models.CharField(max_length=64,verbose_name="出版社名称") 7city = models.CharField(max_length=24,verbose_name="所在城市") 8 9 10def __str__(self): 11 12return self.name 13 14 15 class Author(models.Model): 16 17name = models.CharField(max_length=20,verbose_name="作者名称") 18sex = models.BooleanField(max_length=1,choices=((0,'男'),(1,'女'))) 19email = models.EmailField() 20birthday = models.DateField() 21 22def __str__(self): 23 24return self.name 25 26 27 class Book(models.Model): 28 29title = models.CharField(max_length=64,verbose_name="书名") 30authors = models.ManyToManyField(Author) 31publish = models.ForeignKey(Publisher) 32price = models.DecimalField(max_digits=5,decimal_places=2,default=10) 33 34def __str__(self): 35 36return self.title

创建模型 确认当前app已经添加到settings设置中,然后执行数据库初始化操作: python3 manage.py makemigrations和python3 manage.py migrate。
Python|Python Web框架——Django
文章图片

2django ORM——增(create、save)
增加数据有两种方式: (数据表中的每一条数据代表一个对象)
Python|Python Web框架——Django
文章图片

创建一对多关系:
Python|Python Web框架——Django
文章图片

创建多对多关系:
Python|Python Web框架——Django
文章图片

3django ORM——删(delete)
Python|Python Web框架——Django
文章图片

【Python|Python Web框架——Django】4django ORM——改(update、save)
只有QuerySet对象才有update方法,因此查找行对象时只能使用filter,不能使用get。返回的整数表示受影响的行数。
Python|Python Web框架——Django
文章图片

save方法会将所有属性重新设定一遍,而update只对指定的属性值进行设定,故update方法更高效。
Python|Python Web框架——Django
文章图片

5django ORM——查
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 # 查询相关API: 2 3 #<1>filter(**kwargs):它包含了与所给筛选条件相匹配的对象 4 5 #<2>all():查询所有结果 6 7 #<3>get(**kwargs):返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。 8 9 #-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()-------- 10 11 #<4>values(*field):返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列 12 13 #<5>exclude(**kwargs):它包含了与所给筛选条件不匹配的对象 14 15 #<6>order_by(*field):对查询结果排序 16 17 #<7>reverse():对查询结果反向排序 18 19 #<8>distinct():从返回结果中剔除重复纪录 20 21 #<9>values_list(*field):它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列 22 23 #<10>count():返回数据库中匹配查询(QuerySet)的对象数量。 24 25 # <11>first():返回第一条记录 26 27 # <12>last():返回最后一条记录 28 29 #<13>exists():如果QuerySet包含数据,就返回True,否则返回False。

查询API: Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
>>> Book.objects.all() , , , , , , ]> >>> Book.objects.filter(price__lt=50) , , ]> >>> Book.objects.get(title='python') >>> Book.objects.filter(price__lt=50).values() >>> Book.objects.filter(price__lt=50).exclude(price__gt=60) , , ]> >>> Book.objects.filter(price__lt=50).exclude(id=6) , ]> >>> Book.objects.all().order_by('price') , , , , , , ]> >>> Book.objects.all().reverse() , , , , , , ]> >>> Book.objects.all().distinct() , , , , , , ]> >>> Book.objects.all().values_list() >>> Book.objects.all().count() 7 >>> Book.objects.all().first() >>> Book.objects.all().last() >>> Book.objects.all().exists() True

View Code 扩展查询:
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
#扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra: #extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None(1)Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) (2)Blog.objects.extra( select=SortedDict([('a', '%s'), ('b', '%s')]), select_params=('one', 'two'))(3)q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"}) q = q.extra(order_by = ['-is_recent'])(4)Entry.objects.extra(where=['headline=%s'], params=['Lennon'])extra

View Code 惰性机制:
Book.objects.filter()或Book.objects.all()等只是返回一个QuerySet对象(查询结果集对象),并不会马上执行SQL,而是当调用QuerySet对象时才会执行SQL。
QuerySet特点:
<1>可迭代
Python|Python Web框架——Django
文章图片

<2>可切片
Python|Python Web框架——Django
文章图片

QuerySet的高效使用:

Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 #<1>Django的queryset是惰性的 2 3 Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得到数据库中 4 名字为‘Dave’的所有的人: 5 person_set = Person.objects.filter(first_name="Dave") 6 7 上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数, 8 这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。 9 10 #<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql. 11为了验证这些,需要在settings里加入 LOGGING(验证方式) 12 13obj=models.Book.objects.filter(id=3) 14 15# for i in obj: 16#print(i) 17 18# if obj: 19#print("ok") 20 21 #<3>queryset是具有cache的 22 当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行(evaluation). 23 这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,你不需要重复运行通用的查询。 24obj=models.Book.objects.filter(id=3) 25 26# for i in obj: 27#print(i) 28 29# for i in obj: 30#print(i)#LOGGING只会打印一次 31 32 33 #<4> 34简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些数据! 35 为了避免这个,可以用exists()方法来检查是否有数据: 36 37 obj = Book.objects.filter(id=4) 38 #exists()的检查可以避免数据放入queryset的cache。 39 if obj.exists(): 40print("hello world!") 41 42 #<5>当queryset非常巨大时,cache会成为问题 43 44 处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统进程,让你的 45 程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法来获取数据,处理完数据就 46 将其丢弃。 47 objs = Book.objects.all() 48 # iterator()可以一次只从数据库获取少量数据,这样可以节省内存 49 for obj in objs.iterator(): 50print(obj.name) 51 当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使用iterator() 52 的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询 53 54 总结: 55queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。 56 使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能 57 会造成额外的数据库查询。

View Code 对象查询、单表条件查询、多表条件关联查询:
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 #--------------------对象形式的查找-------------------------- 2# 正向查找 3ret1=models.Book.objects.first() 4print(ret1.title) 5print(ret1.price) 6print(ret1.publisher) 7print(ret1.publisher.name)#因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合 8 9# 反向查找 10ret2=models.Publish.objects.last() 11print(ret2.name) 12print(ret2.city) 13#如何拿到与它绑定的Book对象呢? 14print(ret2.book_set.all()) #ret2.book_set是一个queryset集合 15 16 #---------------了不起的双下划线(__)之单表条件查询---------------- 17 18 #models.Tb1.objects.filter(id__lt=10, id__gt=1)# 获取id大于1 且 小于10的值 19 # 20 #models.Tb1.objects.filter(id__in=[11, 22, 33])# 获取id等于11、22、33的数据 21 #models.Tb1.objects.exclude(id__in=[11, 22, 33])# not in 22 # 23 #models.Tb1.objects.filter(name__contains="ven") 24 #models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感 25 # 26 #models.Tb1.objects.filter(id__range=[1, 2])# 范围bettwen and 27 # 28 #startswith,istartswith, endswith, iendswith, 29 30 #----------------了不起的双下划线(__)之多表条件关联查询--------------- 31 32 # 正向查找(条件) 33 34 #ret3=models.Book.objects.filter(title='Python').values('id') 35 #print(ret3)#[{'id': 1}] 36 37#正向查找(条件)之一对多 38 39ret4=models.Book.objects.filter(title='Python').values('publisher__city') 40print(ret4)#[{'publisher__city': '北京'}] 41ret5=models.Book.objects.filter(publisher__address='北京').values('publisher__name') 42print(ret5)#[{'publisher__name': '人大出版社'}, {'publisher__name': '人大出版社'}] 43 44#正向查找(条件)之多对多 45ret6=models.Book.objects.filter(title='Python').values('author__name') 46print(ret6) 47ret7=models.Book.objects.filter(author__name="alex").values('title') 48print(ret7) 49 50 # 反向查找(条件) 51 52#反向查找之一对多: 53ret8=models.Publisher.objects.filter(book__title='Python').values('name') 54print(ret8)#[{'name': '人大出版社'}]注意,book__title中的book就是Publisher的关联表名 55 56ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors') 57print(ret9)#[{'book__authors': 1}, {'book__authors': 2}] 58 59#反向查找之多对多: 60ret10=models.Author.objects.filter(book__title='Python').values('name') 61print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

View Code
>>> Publisher.objects.filter(book__price__gt=50).values('book__title')

聚合查询和分组查询:
<1> aggregate(*args,**kwargs)
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
from django.db.models import Avg,Min,Sum,Max从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有 图书的集合。>>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35}aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的 标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定 一个名称,可以向聚合子句提供它: >>> Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35}如果你也想知道所有图书价格的最大值和最小值,可以这样查询: >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

View Code <2> annotate(*args,**kwargs)
可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。
查询alex出的书总价格
Python|Python Web框架——Django
文章图片


查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name

Python|Python Web框架——Django
文章图片


查询各个出版社最便宜的书价是多少

Python|Python Web框架——Django
文章图片


F查询和Q查询:
Python|Python Web框架——Django
文章图片
Python|Python Web框架——Django
文章图片
1 # F 使用查询条件的值,专门取对象中某列值的操作 2 3# from django.db.models import F 4# models.Tb1.objects.update(num=F('num')+1) 5 6 7 # Q 构建搜索条件 8from django.db.models import Q 9 10#1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询 11q1=models.Book.objects.filter(Q(title__startswith='P')).all() 12print(q1)#[, ] 13 14# 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。 15Q(title__startswith='P') | Q(title__startswith='J') 16 17# 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合 18Q(title__startswith='P') | ~Q(pub_date__year=2005) 19 20# 4、应用范围: 21 22# Each lookup function that takes keyword-arguments (e.g. filter(), 23#exclude(), get()) can also be passed one or more Q objects as 24# positional (not-named) arguments. If you provide multiple Q object 25# arguments to a lookup function, the arguments will be “AND”ed 26# together. For example: 27 28Book.objects.get( 29Q(title__startswith='P'), 30Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) 31) 32 33#sql: 34# SELECT * from polls WHERE question LIKE 'P%' 35#AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') 36 37# import datetime 38# e=datetime.date(2005,5,6)#2005-05-06 39 40# 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。 41# 正确: 42Book.objects.get( 43Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), 44title__startswith='P') 45# 错误: 46Book.objects.get( 47question__startswith='P', 48Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

View Code
原生SQL的用法:
http://www.cnblogs.com/lijintian/p/6100097.html
附录 Django命令行工具
django-admin.py 是Django的一个用于管理任务的命令行工具,manage.py是对django-admin.py的简单包装,每一个Django Project里都会有一个mannage.py。
1 django-admin.py startproject project_name 创建一个新的django工程。
2 python manage.py startapp app_name 创建一个应用。
3 python manage.py runserver 8080 启动django项目。
4 python manage.py makemigrations migrations目录下生成同步数据库的脚本。
同步数据库:python manage.py migrate
5 python manage.py createsuperuser 创建超级管理员,设置用户名和密码。当我们访问http://http://127.0.0.1:8080/admin/时,便可以通过超级管理员用户登录了。
6 python manage.py flush
清空数据库。
7 django-admin.py help startapp 查询某个命令的详细信息。
8 python manage.py shell 启动交互界面。
9 python manage.py 查看django提供的命令。

转载于:https://www.cnblogs.com/pyramid1001/p/6089689.html

    推荐阅读