django 请求流程图
django 路由系统
在django中我们可以通过定义urls,让不同的url路由到不同的处理函数
from . import views urlpatterns = [ 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), ]
注意: url的位置对于url的匹配是有影响的,url按照正则匹配,上面的匹配到了,下面的就不会被匹配了。
默认url
urlpatterns = [ url(r‘^$‘, views.index), url(r‘index2/$‘, views.index2), ]
当匹配不到任何url的时候,将执行默认url。
动态url
动态url传参
当我们想查找某年内的文章时,每点击一个url就需要写一个url匹配,这样显然是不合理的,所以我们可以通过动态url匹配,通过正则来实现。可以将参数传给后端函数处理。
urlpatterns = [ 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), ]
对于url(r‘^articles/([0-9]{4})/$‘, views.year_archive) 这条匹配规则,views函数必须为/([0-9]{4})有一个接收参数,否则将提示
动态url传入关键字参数
我的参数过多的时候,按照顺序传入就会显得很麻烦,这时候我们可以按照key:value形式传入参数
import views urlpatterns = [ url(r‘^articles/2003/$‘, views.special_case_2003), url(r‘^articles/(?P<year>[0-9]{4})/$‘, views.year_archive), url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$‘, views.month_archive), url(r‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$‘, views.article_detail), ]
当我们请求/articles/2005/03/
将会调用后端函数传入year和month参数 views.month_archive(request, year=‘2005‘,month=‘03‘),假设我们将在函数定义中把year和month写成y和m,
将会出现错误。
url转发
大部分情况下,我们不会把所有的url写在全局url配置中,这样会容易引发很多问题,比如:
新增加的url规则可能包含旧的url,导致旧的匹配不到,
添加错误的url导致站点出现问题
app间的松耦合问题
...
所以我们应该使用以下方式解决问题:
在全局urls.py中添加,二层路由
from django.conf.urls import url,include from app01 import urls as payment_urls urlpatterns = [ url(r‘^payment/‘, include(payment_urls)), ]
在app中添加urls.py文件
from django.conf.urls import url,include from app01 import views urlpatterns = [ url(r‘^$‘, views.index), url(r‘cash/$‘, views.pay_by_cash), ]
接下里可以通过 http://hostip:port/payment/ 或 http://hostip:port/payment/cash/ 访问
注意:django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
django templates
django的模板给我们提供了丰富的替换规则,假设我们自己去定义一个替换规则如下:
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
当内容足够多的时候,就没法玩了。当然我们可以写入文件,然后通过django的模板语言渲染html。
Django 模版基本语法
>>> from django.template import Context,Template >>> t = Template("my name is {{name}}.") #针对变量 >>> c = Context({"name":"koka"}) >>> t.render(c) ‘my name is koka.‘ >>> from django.template import Template,Context >>> person = {"name":"koka","age":"24"} #针对字典 >>> t = Template("{{ person.name }} is {{ person.age }} year old.") >>> c = Context({"person":person}) >>> t.render(c) ‘koka is 24 year old.‘ >>> t = Template("Item 2 is {{ items.2 }}.") #针对列表 >>> c = Context({‘items‘:["apples","bananas","carrots"]}) >>> t.render(c) ‘Item 2 is carrots.‘
无论何时我们都可以像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会更为高效:
注意:
Django 模板解析非常快捷。 大部分的解析工作都是在后台通过对简短正则表达式一次性调用来完成。 这和基于 XML 的模板引擎形成鲜明对比,那些引擎承担了 XML 解析器的开销,且往往比 Django 模板渲染引擎要慢上几个数量级。我们来对比一下两种方式:
# Bad for name in (‘John‘, ‘Julie‘, ‘Pat‘): t = Template(‘Hello, {{ name }}‘) #建立多次模板 print t.render(Context({‘name‘: name})) # Good t = Template(‘Hello, {{ name }}‘) for name in (‘John‘, ‘Julie‘, ‘Pat‘): print t.render(Context({‘name‘: name}))
模板中的for和if语句,django模板语言是没有while循环的,假设写一个死循环一直获取不到数据,将是一件悲剧的事。
for: {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
if: {% if ordered_warranty %} {% else %} {% endif %}
#templates中定义index.html模板文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .header li{ display: inline-block; } </style> </head> <body> <div class="header"> <ul> <li>home</li> <li>page1</li> <li>page2</li> <li>page3</li> </ul> </div> <h1>Welcome to test center</h1><ul> {% for item in user_obj %} {% if item.username == "koka" %} <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li> {% else %} <li style="">username:{{ item.username }} age:{{ item.age }}</li> {% endif %} {% endfor %} </ul><footer> Power by koka</footer> </body> </html>
#view
from django.shortcuts import render,HttpResponse # Create your views here. def index(request): user_obj = [ {"username":"koka", "age":"24"}, {"username":"ajax", "age":"24"}, {"username":"django","age":"24"} ] return render(request, ‘app01/index.html‘, {‘user_obj‘: user_obj}) #将数据插入模板文件
其他方法:
- forloop.counter
- forloop.first
- forloop.last
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Welcome to test center</h1> <ul> {% for item in user_obj %} {% if forloop.counter > 2 %} <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li> {% else %} <li style="">username:{{ item.username }} age:{{ item.age }}</li> {% endif %} {% endfor %} </ul> </body> </html>
效果如下:
divisibleby 取模
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>Welcome to test center</h1> <ul> {% for item in user_obj %} {% if forloop.counter|divisibleby:"2" %} <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li> {% else %} <li style="">username:{{ item.username }} age:{{ item.age }}</li> {% endif %} {% endfor %} </ul> </body> </html>
效果如下:
django母板与子板
母板:{% block title %}{% endblock %} 定义子板可以修改的范围
子板:{% extends "base.html" %} 继承母板
{% block title %}{% endblock %} 重写母板中定义可以修改的范围
继承与重写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .header li{ display: inline-block; } </style> </head> <body> <div class="header"> <ul> <li>home</li> <li>page1</li> <li>page2</li> <li>page3</li> </ul> </div> <h1>Welcome to test center</h1> {% block tab %} <ul> {% for item in user_obj %} {% if item.username == "koka" %} <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li> {% else %} <li style="">username:{{ item.username }} age:{{ item.age }}</li> {% endif %} {% endfor %} </ul> {% endblock %} <footer> Power by koka</footer> </body> </html>
母板
{% extends ‘app01/index.html‘ %} {% block tab %} <h1>this is my page</h1> <form style="color: aqua" action="#" method="post"> UserName:<input name="username" type="text"> Password:<input name="pwd" type="password"> </form> {% endblock %}
子板
多重继承
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .header li{ display: inline-block; } </style> </head> <body> <div class="header"> <ul> <li>home</li> <li>page1</li> <li>page2</li> <li>page3</li> </ul> </div> <h1>Welcome to test center</h1> {% block tab %} <ul> {% for item in user_obj %} {% if item.username == "koka" %} <li style="background-color: red;">username:{{ item.username }} age:{{ item.age }}</li> {% else %} <li style="">username:{{ item.username }} age:{{ item.age }}</li> {% endif %} {% endfor %} </ul> {% endblock %} <footer> Power by koka</footer> </body> </html>
母板 index
{% extends ‘app01/index.html‘ %} {% block tab %} <h1>this is sub page</h1> {% block f-content %} {% include ‘app01/register_form.html‘ %} {% endblock %} {% endblock %}
{% extends "app01/page1.html" %} {% block f-content %} <h1>this is sub-sub-page</h1> {% endblock %}
include
在讲解了模板加载机制之后,我们再介绍一个利用该机制的内建模板标签: {% include %} 。该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号硬编码的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <form style="color: aqua" action="#" method="post"> UserName:<input name="username" type="text"> Password:<input name="pwd" type="password"> </form> </body> </html>
form_register
{% extends ‘app01/index.html‘ %} {% include ‘app01/register_form.html‘ %}
django admin
django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:
1.注册app
INSTALLED_APPS = [ ‘django.contrib.admin‘, ‘django.contrib.auth‘, ‘django.contrib.contenttypes‘, ‘django.contrib.sessions‘, ‘django.contrib.messages‘, ‘django.contrib.staticfiles‘, ‘app01‘, ]
2.数据库配置
DATABASES = { ‘default‘: { #sqlite配置如下 ‘ENGINE‘: ‘django.db.backends.sqlite3‘, ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘), # mysql配置如下 # ‘ENGINE‘: ‘django.db.backends.mysql‘, # ‘NAME‘: ‘s12day16‘, # ‘HOST‘: ‘‘, # ‘PORT‘: ‘‘, # ‘USER‘: ‘root‘, # ‘PASSWORD‘: ‘‘, } }
3.models配置
from django.db import models # Create your models here. class Publisher(models.Model): name = models.CharField(max_length=32) address = models.CharField(max_length=64,unique=True) city = models.CharField(max_length=64) state_province = models.CharField(max_length=32) country = models.CharField(max_length=32) website = models.URLField() def __unicode__(self): return "%s" % self.name def __str__(self): return "%s" % self.name class Author(models.Model): first_name = models.CharField(max_length=32) last_name = models.CharField(max_length=32) email = models.EmailField() def __unicode__(self): return "%s %s" %(self.first_name,self.last_name) def __str__(self): return "%s %s" %(self.first_name,self.last_name) class Book(models.Model): title = models.CharField(max_length=64) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return "%s" % self.title def __str__(self): return "%s" % self.title
models
4.创建数据库
终端下执行下面两条命令:
python manage.py makemigrations 生成数据库配置文件
python manage.py migrate 创建数据库
5.配置admin
from django.contrib import admin # Register your models here. from app01 import models admin.site.register(models.Author) admin.site.register(models.Book) admin.site.register(models.Publisher)
6.创建超级管理员
pyhton manage.py createsuperuser
7.登录admin管理后台
http://hostip:port/admin
设置字段可选
在摆弄了一会之后,你或许会发现管理工具有个限制:编辑表单需要你填写每一个字段,然而在有些情况下,你想要某些字段是可选的。 举个例子,我们想要Author模块中的email字段成为可选,即允许不填。 在现实世界中,你可能没有为每个作者登记邮箱地址。
为了指定email字段为可选,你只要编辑Book模块(回想第五章,它在mysite/books/models.py文件里),在email字段上加上blank=True。代码如下:
class Author(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField(**blank=True** )
设置日期型和数字型字段可选
在SQL中, NULL的值不同于空字符串,就像Python中None不同于空字符串("")一样。这意味着某个字符型字段(如VARCHAR)的值不可能同时包含NULL和空字符串。
如果你想允许一个日期型(DateField、TimeField、DateTimeField)或数字型(IntegerField、DecimalField、FloatField)字段为空,你需要使用null=True * 和* blank=True。
class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField(**blank=True, null=True** )
修改了表结构,需要重新同步数据库。
自定义字段标签
在编辑页面中,每个字段的标签都是从模块的字段名称生成的。 规则很简单: 用空格替换下划线;首字母大写。例如:Book模块中publication_date的标签是Publication date。
然而,字段名称并不总是贴切的。有些情况下,你可能想自定义一个标签。 你只需在模块中指定verbose_name。
class Author(models.Model): first_name = models.CharField(max_length=30,verbose_name=‘名‘) last_name = models.CharField(max_length=40,verbose_name=‘姓‘) email = models.EmailField(blank=True, **verbose_name=‘邮箱‘** )
自定义ModelAdmin类
自定义列表
自定义显示字段否则将是tableobj
class Author(models.Model): first_name = models.CharField(max_length=32) last_name = models.CharField(max_length=32) email = models.EmailField() def __unicode__(self): #1.9以前 return "%s %s" %(self.first_name,self.last_name) def __str__(self): #1.9以后 return "%s %s" %(self.first_name,self.last_name)
我们可以在这基础上改进,添加其它字段,从而改变列表的显示。
这个页面应该提供便利,比如说:在这个列表中可以看到作者的邮箱地址。如果能按照姓氏或名字来排序,那就更好了。
from django.contrib import admin # Register your models here. from app01 import models class AuthorAdmin(admin.ModelAdmin): // 我们新建了一个类AuthorAdmin,它是从django.contrib.admin.ModelAdmin派生出来的子类,保存着一个类的自定义配置,以供管理工具使用。 我们只自定义了一项:list_display, 它是一个字段名称的元组,用于列表显示。 当然,这些字段名称必须是模块中有的。 // list_display = (‘first_name‘, ‘last_name‘, ‘email‘) admin.site.register(models.Author,AuthorAdmin) //用AuthorAdmin选项注册Author模块。admin.site.register()函数接受一个ModelAdmin子类作为第二个参数。 admin.site.register(models.Book) admin.site.register(models.Publisher)
效果如下:
添加一个快速查询栏
class AuthorAdmin(admin.ModelAdmin): list_display = (‘first_name‘, ‘last_name‘, ‘email‘) **search_fields = (‘first_name‘, ‘last_name‘)**
过滤器
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) admin.site.register(models.Book,BookAdmin)
`` 过滤器`` 同样适用于其它类型的字段,而不单是`` 日期型`` (请在`` 布尔型`` 和`` 外键`` 字段上试试)。当有两个以上值时,过滤器就会显示。
另外一种过滤日期的方式是使用date_hierarchy选项
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) date_hierarchy = ‘publication_date‘
请注意,date_hierarchy接受的是* 字符串* ,而不是元组。因为只能对一个日期型字段进行层次划分。
改变默认的排序方式
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) date_hierarchy = ‘publication_date‘ **ordering = (‘-publication_date‘,)**
自定义编辑表单
自定义字段顺序
首先,我们先自定义字段顺序。 默认地,表单中的字段顺序是与模块中定义是一致的。 我们可以通过使用ModelAdmin子类中的fields选项来改变它:
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) date_hierarchy = ‘publication_date‘ ordering = (‘-publication_date‘,) **fields = (‘title‘, ‘authors‘, ‘publisher‘, ‘publication_date‘)**
完成之后,编辑表单将按照指定的顺序显示各字段。 它看起来自然多了——作者排在书名之后。 字段顺序当然是与数据条目录入顺序有关, 每个表单都不一样。
禁止编辑项
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) date_hierarchy = ‘publication_date‘ ordering = (‘-publication_date‘,) **fields = (‘title‘, ‘authors‘, ‘publisher‘)** #不包含某一项即可
ctrl多选框
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) date_hierarchy = ‘publication_date‘ ordering = (‘-publication_date‘,) **filter_horizontal = (‘authors‘,)**
ModelAdmin类还支持filter_vertical选项。 它像filter_horizontal那样工作,除了控件都是垂直排列,而不是水平排列的。
filter_horizontal和filter_vertical选项只能用在多对多字段 上, 而不能用于 ForeignKey字段。 默认地,管理工具使用`` 下拉框`` 来展现`` 外键`` 字段。
文本框
使用`` raw_id_fields`` 选项。它是一个包含外键字段名称的元组,它包含的字段将被展现成`` 文本框`` ,而不再是`` 下拉框`` 。
class BookAdmin(admin.ModelAdmin): list_display = (‘title‘, ‘publisher‘, ‘publication_date‘) list_filter = (‘publication_date‘,) date_hierarchy = ‘publication_date‘ ordering = (‘-publication_date‘,) filter_horizontal = (‘authors‘,) **raw_id_fields = (‘publisher‘,)**
更多django admin的内容请参考: http://docs.30c.org/djangobook2/chapter06/
django models
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:
- 创建数据库,设计表结构和字段
- 使用sqlapi 来连接数据库,并编写数据访问层代码
- 业务逻辑层去调用数据访问层执行数据库操作
第一个模型
我们来假定下面的这些概念、字段和关系:
- 一个作者有姓,有名及email地址。
- 出版商有名称,地址,所在城市、省,国家,网站。
- 书籍有书名和出版日期。 它有一个或多个作者(和作者是多对多的关联关系[many-to-many]), 只有一个出版商(和出版商是一对多的关联关系[one-to-many],也被称作外键[foreign key])
from django.db import models # Create your models here. class Publisher(models.Model): #首先要注意的事是每个数据模型都是 django.db.models.Model 的子类。 #它的父类 Model 包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法。 name = models.CharField(max_length=32) address = models.CharField(max_length=64,unique=True) city = models.CharField(max_length=64) state_province = models.CharField(max_length=32) country = models.CharField(max_length=32) website = models.URLField() def __unicode__(self): return "%s" % self.name def __str__(self): return "%s" % self.name class Author(models.Model): #每个模型相当于单个数据库表,每个属性也是这个表中的一个字段。 first_name = models.CharField(max_length=32) last_name = models.CharField(max_length=32) email = models.EmailField(verbose_name="邮箱") def __unicode__(self): return "%s %s" %(self.first_name,self.last_name) def __str__(self): return "%s %s" %(self.first_name,self.last_name) class Book(models.Model): #“每个数据库表对应一个类”这条规则的例外情况是多对多关系。 # Book 有一个 多对多字段 叫做 authors 。 该字段表明一本书籍有一个或多个作者,但 Book 数据库表却并没有 authors 字段。 #相反,Django创建了一个额外的表(多对多连接表)来处理书籍和作者之间的映射关系。 title = models.CharField(max_length=64) authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) publication_date = models.DateField() def __unicode__(self): return "%s" % self.title def __str__(self): return "%s" % self.title
Django会自动为每个模型生成一个自增长的整数主键字段每个Django模型都要求有单独的主键。id
剩下的步骤参考django admin生成数据库的操作。(注册,生成配置文件,创建数据库)
1、models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField 字符串字段 必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) 不能为空,Blank=True 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField 日期类型 datetime 同DateField的参数 7、models.Decimal 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar 对字符串进行正则表达式 9、models.FloatField 浮点类型 = double 10、models.IntegerField 整形 11、models.BigIntegerField 长整形 integer_field_ranges = { ‘SmallIntegerField‘: (-32768, 32767), ‘IntegerField‘: (-2147483648, 2147483647), ‘BigIntegerField‘: (-9223372036854775808, 9223372036854775807), ‘PositiveSmallIntegerField‘: (0, 32767), ‘PositiveIntegerField‘: (0, 2147483647), } 12、models.IPAddressField 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的) 参数protocol可以是:both、ipv4、ipv6 验证时,会根据设置报错 14、models.NullBooleanField 允许为空的布尔类型 15、models.PositiveIntegerFiel 正Integer 16、models.PositiveSmallIntegerField 正smallInteger 17、models.SlugField 减号、下划线、字母、数字 18、models.SmallIntegerField 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField 字符串=longtext 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField 字符串,地址正则表达式 22、models.BinaryField 二进制 23、models.ImageField 图片 24、models.FilePathField 文件
更多字段
1、null=True 数据库中字段是否可以为空 2、blank=True django的 Admin 中添加数据时是否可允许空值 3、primary_key = False 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add auto_now 自动创建---无论添加或修改,都是当前操作的时间 auto_now_add 自动创建---永远是创建时的时间 5、choices GENDER_CHOICE = ( (u‘M‘, u‘Male‘), (u‘F‘, u‘Female‘), ) gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default 默认值 8、verbose_name Admin中字段的显示名称 9、name|db_column 数据库中的字段名称 10、unique=True 不允许重复 11、db_index = True 数据库索引 12、editable=True 在Admin里是否可编辑 13、error_messages=None 错误提示 14、auto_created=False 自动创建 15、help_text 在Admin中提示帮助信息 16、validators=[] 17、upload-to
更多参数
参考地址:
https://docs.djangoproject.com/en/1.9/ref/models/fields/
数据库的基本操作
添加数据
python manage.py shell
方式一:
>>> p1 = models.Publisher(name="Apress",address="2855 Tele Aven",city="Bkl",state_province="CA",country=‘U.S.A.‘,website="http://apress.com/") #当你使用Django modle API创建对象时Django并未将对象保存至数据库内,除非你调用`` save()`` 方法: >>> p1.save() #后台插入数据库因为 Publisher 模型有一个自动增加的主键 id ,所以第一次调用 save() 还多做了一件事: 计算这个主键的值并把它赋值给这个对象实例:
方式二:
>>> models.Author.objects.create(first_name="lo",last_name="lo",email="[email protected]") <Author: lo lo> >>> models.Author.objects.create(first_name="la",last_name="la",email="[email protected]") <Author: la la>
插入和更新数据
>>> p2 = models.Publisher(name="wlgc",address="cnblog", city="BJ",state_province="BJ",country="CN",website="http://www.wlgc.com/") >>> p2.save() >>> p2.id 4 接下来再调用 save() 将不会创建新的记录,而只是修改记录内容(也就是 执行 UPDATE SQL语句,而不是 INSERT 语句): >>> p2.address = ‘WLGC‘ >>> p2.save()
注意,并不是只更新修改过的那个字段,所有的字段都会被更新。 这个操作有可能引起竞态条件(表之间的关联冲突),这取决于你的应用程序。
查找数据
>>> models.Publisher.objects.all() #查找所有[<Publisher: DB出版社>, <Publisher: dbrc出版社>, <Publisher: Apress>, <Publisher: wlgc>]
>>> models.Publisher.objects.all().last()<Publisher: wlgc> >>> models.Publisher.objects.all().first()<Publisher: DB出版社>
数据过滤
`` filter()`` 方法对数据进行过滤 >>> models.Publisher.objects.filter(name="Apress") [<Publisher: Apress>] 你可以传递多个参数到 filter() 来缩小选取范围:>>> models.Publisher.objects.filter(country="U.S.A.", state_province="CA")[<Publisher: Apress>] 范围匹配id在1-3之间>>> models.Publisher.objects.filter(id__range=[1,3])[<Publisher: DB出版社>, <Publisher: dbrc出版社>]
模糊匹配
>>> models.Publisher.objects.filter(name__contains="press") [<Publisher: Apress>]
>>> models.Publisher.objects.filter(name__icontains="press") [<Publisher: Apress>]
在 name 和 contains 之间有双下划线。和Python一样,Django也使用双下划线来表明会进行一些魔术般的操作。这里,contains部分会被Django翻译成LIKE语句,icontains不区分大小写:
获取单个对象
>>> models.Publisher.objects.get(name="Apress") <Publisher: Apress> 这样,就返回了单个对象,而不是列表(更准确的说,QuerySet)
注意:使用get请求到一个列表或者空字段时将会报错
结果是多个对象,会导致抛出异常: >>> Publisher.objects.get(country="U.S.A.") Traceback (most recent call last): ... MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2! Lookup parameters were {‘country‘: ‘U.S.A.‘} 查询没有返回结果也会抛出异常: >>> Publisher.objects.get(name="Penguin") Traceback (most recent call last): ... DoesNotExist: Publisher matching query does not exist. 这个 DoesNotExist 异常 是 Publisher 这个 model 类的一个属性,即 Publisher.DoesNotExist。在你的应用中,你可以捕获并处理这个异常,像这样: try: p = Publisher.objects.get(name=‘Apress‘) except Publisher.DoesNotExist: print "Apress isn‘t in the database yet." else: print "Apress is in the database."
更新多个对象(update)
>>> models.Author.objects.filter(id=3).update(first_name="db")1>>> models.Publisher.objects.all().update(country=‘CN‘)4update()方法会返回一个整型数值,表示受影响的记录条数。
删除对象(delete)
>>> models.Publisher.objects.get(name="Apress").delete() (1, {‘app01.Publisher‘: 1})
>>> models.Publisher.objects.all().delete() #删除所有Publisher
关联查找
>>> b1 = models.Book.objects.get(id=2) >>> b1.authors.select_related() [<Author: sp chai>]