这一节主要介绍对数据库的访问操作:通过管理器(manage),对对象进行检索、修改、删除等操作,详细介绍了如何针对不同的模型自定义管理器。

查询和管理工作

现在,我们已经有了一个功能完善的Django管理站点来管理我们的应用,是时候学习一下如何从数据库中检索我们所需要的数据。Django自带一个功能强大的抽象数据库API,使我们能轻松的创建、检索、修改、和删除对象。Django的对象关系映射(ORM)兼容MySQL,PostgreSQL,SQLite,Oracle。

记住,你可以在settings.py文件中自定义你想使用的数据库。Django可以同时运行复数数据库,甚至可以用你喜欢的方式来操作远程数据库。

一旦你已经创建了你的数据模型,就可以使用API来操作它们。想要知道更多有关于数据模型的信息,可以访问:https://docs.djangoproject.com/en/1.8/ref/models/.

创建对象

打开终端输入以下命令来打开交互界面:

python manage.py shell

输入以下内容:

>>>  from django.contrib.auth.models import User
>>> from blog.models import Post
>>> user = User.objects.get(username='admin')
>>> Post.objects.create(title='One more post', slug='one-more-post', body='Post body.', author=user)
>>> post.save ()

让我们分析一下上面的代码:

首先,我们检索用户名为admin的User对象。

user = User.objects.get(username='admin')

get()方法允许你从数据库中检索单个对象,这个方法返回一个匹配的对象,如果没有检索到该对象,这个方法将会抛出DoesNotExist(对象不存在)的错误。如果有多个结果匹配,则会抛出一个MultipleObjectsReturned(返回复数对象)的错误,这两个异常都是当前正在查询的模型类的属性。

接着,我们创建一个自定义的标题(title)、简短标题(slug)、文章内容(body)、还有设置我们刚才检索出来的user对象,作为文章的作者(Author)

post = Post(title='Another post', slug='another-post', body='Post body.', author=user)

然后,我们用save()方法来保存刚刚创建的Post对象。

post.save()

这一动作将会在SQL后台注入Post对象,我们已经知道如何在内存中创建一个Post对象并把它保存到数据库中。当然,我们也可以用create()方法来直接在数据库中创建一个Post对象。

Post.objects.create(title='One more post', slug='one-more-post', body='Post body.', author=user)

更新对象

现在,我们改变一下刚刚创建的Post对象的标题并再次保存它:

>>>  post.title = 'New title'
>>> post.save ()

这次,save()方法执行了更新数据库(UPDATE SQL)语句

注意:直到你执行save()方法,你对对象的更改才会保存到数据库中。

检索对象

Django的对象关系映射(ORM)基于QuerySet(查询集),你可以通过多种过滤方式来限制返回结果。你已经知道可以通过get()方法来从数据库中获取单个对象。正如你所见,可以使用Post.objects.get()来获取指定对象。每个Django模型至少含有一个名叫objects的默认管理器。在不知不觉中,你已经通过控制器获取了对象。同样,你也可以使用Post.objects.all()来获取所有对象。

>>> all_posts = Post.objects.all()

这就是如何从一个数据库中获取所有对象的方法:通过管理器objects要求它返回所有对象。但是要注意一点:上述语句并没有在数据库中立即执行,究其原因,是因为QuerySet其实非常“懒惰”,它会谨慎的评估是否需要立即执行SQL语句。而正是因为这个“懒惰”的特性,才让它十分高效。举个例子说吧:如果我们不是把QuerySet保存到变量(all_posts = Post.objects.all()),而是打开Python shell,输入Post.objects.all(),SQL语句就会立即执行,是因为我们“强迫”它给我们一个交代:把查询结果输出到控制台.

>>> Post.objects.all()

使用管理器的filter()方法

如果我们只想查询符合条件的对象集合,可以使用管理器的filter()方法。举个例子,如果我们只想从所有对象中查询2015年发布的文章,那么可以用:Post.objects.filter(publish__year=2015)

还有,你可以添加复数过滤条件。例如,我们想查询作者Admin在2015年发布的文章:

Post.objects.filter(publish__year=2015, author__username='admin')

Post.objects.filter(publish__year=2015)\
.filter(author__username='admin')

以上两条语句可以达到相同的查询结果。

不知道你有没有注意到,我们使用字段过滤查询结果,连着用了两个下划线(publish__year),而访问相关联模型(User)的字段(author)时,也用了两个下划线(author_username)。

使用管理器的exclud()方法

有时候你想从过滤结果中剔除不合格的结果,可以使用管理器的exclud()方法,比如,我们想查询所有2015年发布的文章,但是剔除以“Why”开头的文章:

Post.objects.filter(publish__year=2015)\
.exclude(title__startswith='Why')

使用管理器的order_by()方法

如果想要让查询结果按照某种规则排序的时候,可以使用管理器的order_by()方法。举个例子,如果你想让查询结果按照发布日期升序排序,可以使用:(译者注:原文是使用title作为排序方式,也就是按字母排序,译者觉得如果是中文标题按照title排序,效果不明显,所以改用publish排序)

Post.objects.order_by('publish')

升序规则是默认的,如果你想让查询结果按照发布日期降序排序,可以这么做:

Post.objects.order_by('-publish')

使用管理器的order_by()方法

如果你想删除某个对象,可以用:

post = Post.objects.get(id=1)
post.delete()

请注意一点,删除这个对象,意味着同样删除了与其有关的对象。(译者注:例如,删除了一个作者对象,则这个作者所写的所有文章都会随之删除。)

数据库何时真正执行语句

前面讲过,QuerySet其实是非常“懒惰”的,你可以添加任意多的筛选条件,但是Queryset不会马上执行,而是谨慎的对语句进行评估,当它认为有必要执行SQL语句的时候,它才会执行。那什么情况下才是必要的?

  • 第一次遍历查询结果的时候
  • 当对查询结果进行切片操作的时候:Post.objects.all()[:3]
  • 当对查询结果进行缓存操作的时候
  • 使用repr()或者len() 的时候
  • 明确要求遍历list()查询结果的时候
  • 在以下测试语句中:bool(), or , and, if

创建自定义模型管理器

前面讲过,objects是模型的默认管理器,每一个模型都有一个objects管理器,用于对数据库的检索操作。但是,我们想为我们的模型自定义一个管理器,该怎么办呢?比如说,我们想要创建一个获取所有已发布文章的管理器。

这里有两种方式来创建:为原始管理器添加额外的方法,或是修改默认管理器来创建新的管理器。前面一种就变成了Post.objects.my_manager(),后面一种则变成Post.my_manager.all()

我们推荐后一种方法,比如我们为Post模型创建了一个名为Published的管理器:

打开models.py文件天际一个自定义管理器:

class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager,self).get_queryset().filter(status='published') class Post(models.Model):
# ...
objects = models.Manager() # 默认管理器.
published = PublishedManager() # 我们定义的管理器.

PublishedManager显式调用父类的get_queryset()方法,返回一个包含所有对象的QuerySet,再由filter()过滤,得到一个新的QuerySet。至此,我们创建了一个新的管理器,并将它添加到Post模型中,现在我们可以用它来执行查找操作。例如,我们想查找已经发布的文章中,标题以”who“开头的文章。

Post.published.filter(title__startswith='Who')

原文链接:http://www.landsblog.com/blog/content/djangoexamplequery

更多教程:http://www.landsblog.com/blog/tag/django

Django1.8教程——从零开始搭建一个完整django博客(三)的更多相关文章

  1. Django1.8教程——从零开始搭建一个完整django博客(一)

    第一个Django项目将是一个完整的博客网站.它和我们博客园使用的博客别无二致,一样有分类.标签.归档.查询等功能.如果你对Django感兴趣的话,这是一个绝好的机会.该教程将和你一起,从零开始,搭建 ...

  2. Django1.8教程——从零开始搭建一个完整django博客(二)

    在上一节中,我们已经创建了一个Django模型Post,并使Post模型与数据库同步.这一节中,我们将介绍Django管理站点,通过Django管理站点来管理我们创建的Post模型实例. 为你的模型创 ...

  3. 用express搭建一个简单的博客系统

    转自:https://blog.csdn.net/qq_29721837/article/details/62055603 Express 简介 Express 是一个简洁而灵活的 node.js W ...

  4. 使用Hexo搭建一个简单的博客(二)

    昨天想着用Hexo和github搭一个自己简单的博客,记录一下自己踩过的坑,具体的流程就不重复了,主要参考了一下几篇文章 GitHub+Hexo 搭建个人网站详细教程 使用Hexo+Github一步步 ...

  5. 使用Hexo搭建一个简单的博客(一)

    搭建好简洁的博客框架后,回看时发现,简洁之中透露着一丝丝简陋,好的,网上关于丰富hexo的文章也很多 记录一下自己的一些瞎操作. 在你的hexo目录下,你可以看到themes文件夹里有个默认的land ...

  6. 使用Hugo,只需5分钟,轻松搭建一个自己的博客

    前面跟大家介绍过hexo这款静态博客系统,功能强大,基本能满足博客的各种需求.今天,我再跟大家介绍一款优秀的静态博客系统,那就是Hugo. Hugo是由Go语言实现的静态网站生成器.简单.易用.高效. ...

  7. Express入门教程:一个简单的博客

    来自:  http://ourjs.com/detail/56b2a6f088feaf2d031d2468 Express 简介 Express 是一个简洁而灵活的 node.js Web应用框架, ...

  8. 从零开始搭建一个react项目

    Nav logo 120 发现 关注 消息 4 搜索 从零开始搭建一个react项目 96 瘦人假噜噜 2017.04.23 23:29* 字数 6330 阅读 32892评论 31喜欢 36 项目地 ...

  9. react全家桶从0搭建一个完整的react项目(react-router4、redux、redux-saga)

    react全家桶从0到1(最新) 本文从零开始,逐步讲解如何用react全家桶搭建一个完整的react项目.文中针对react.webpack.babel.react-route.redux.redu ...

随机推荐

  1. Spring自定义一个拦截器类SomeInterceptor,实现HandlerInterceptor接口及其方法的实例

    利用Spring的拦截器可以在处理器Controller方法执行前和后增加逻辑代码,了解拦截器中preHandle.postHandle和afterCompletion方法执行时机. 自定义一个拦截器 ...

  2. 设计模式C#实现(二)——适配器模式

    适配器模式:将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 如果它走起路来像只鸭子,叫起来像只鸭子,那么它必定可能是一只鸭子包装了鸭子适配器的火鸡…… 最近有一个 ...

  3. C语言的函数

    "函数"在英文的翻译是"function",无论在自然科学还是计算机科学都是这个词,而"function"的本意是"功能" ...

  4. iOS -数据库网络之xml解析之远程解析XML

    1.IOS中XML文件获取    //设置远程访问地址     NSURL *url=[NSURL URLWithString:@""];       //创建动态URL请求,并初 ...

  5. android linker (1) —— __linker_init()

    ilocker:关注 Android 安全(新手) QQ: 2597294287 __linker_init() 在 begin.S 中被调用,并传入两个参数:sp(堆栈指针).#0. linker( ...

  6. visual studio 2013 快捷键大全

    1.回到上一个光标位置/前进到下一个光标位置 1)回到上一个光标位置:使用组合键“Ctrl + -”: 2)前进到下一个光标位置:“Ctrl + Shift + - ”. 2.复制/剪切/删除整行代码 ...

  7. 迅为iTOP-4412嵌入式开发板实现中断驱动例程

    本文转自迅为:www.topeetboard.com 大家好,今天我们来学习一下 linux 中断处理驱动的编写,本节我们实现的功能是通过开发板上的按键来控制 led 发光二极管,在之前的章节我们学习 ...

  8. [转]highcharts图表入门之:如何让highcharts图表自适应浏览器窗体的大小或者页面大小

    本文转自: http://jsfiddle.net/vCZ8V/1/ http://www.stepday.com/topic/?740 http://blog.csdn.net/yueritian/ ...

  9. css中table tr:nth-child(even)改变tr背景颜色: IE7,8无效

    例如: .my_table tr:nth-child(even){ background:#E6EDF5; } .my_table tr:nth-child(odd){ background:#F0F ...

  10. eclipse菜单解释及中英对照

    在使用Eclipse作为开发工具的时候,建议使用英文版本的(直接百度从官网下就行,这里不详细描述,如果有问题,咱们私聊).虽然中文版本的对于和我一样对英文是小白的看起来特别爽,但是公司大多是英文版本的 ...