1.5 与QuertSet和管理器协同工做

  前述内容设置了一个全功能管理站点,并可对博客内容进行处理.本节将讨论如何从数据库中获取信息并与其进行交互.Django设置了强大的数据库抽象API,并以此方便地建立、获取、更新以及删除对象.同时,Django中的对象关系映射器兼容于MySQL、PostgreSQL、SQLite、Oracle.须要注意的是,咱们可在项目的settings.py文件中的DATABASES设置项中定义当前项目的数据库.Django可一次与多个数据库协同工做,用户能够对数据库路由器进行编程,以建立自定义路由方案.python

  

  在数据库模型建立完毕后,Django提供了相应的API可与其进行交互.shell

 

1.5.1 建立对象数据库

  打开终端并运行如下命令启动Python shell:django

python manage.py shell

  随后输入下列代码行编程

from django.contrib.auth.models import User
from blog.models import Post
user = User.objects.get(username='admin')
post = Post(title='Another post',slug='another-post',body='Post body',author=user)
post.save()

  

  下面对上述代码的执行内容进行简要分析.首先,咱们经过用户名admin获取user对象,以下所示:缓存

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

  这里,get()方法可从数据库中获取单一对象.注意,该方法指望获得与查询匹配的结果.若是数据库未返回任何结果,该方法将会抛出DoesNotExist异常:若是数据库返回多条结果,则会抛出MultipleObjectsReturned异常.这两个异常均为与执行查询对应的、模型类的属性.服务器

  随后利用定制title、slug以及body建立Post实例,并将以前检索到的用户设置为帖子的做者,以下所示:post

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

 

 

  !!!注意:测试

    此类对象位于内存中,且未实现数据库的持久化操做.spa

    最后,利用save()方法将Post对象保存至数据库,以下所示:

post.save()

  上述操做在后台执行了INSERT SQL语句.前述内容讨论了在内存中建立对象,并于随后将其持久化至数据库中.除此以外,还可经过create()这一单一操做方式建立对象,并将其持久化至数据库中,以下所示:

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

 

1.5.2 更新对象

  下面修改帖子的标题,并再次保存对象,对应代码以下所示:

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

  此处,save()方法执行UPDATE SQL语句.

  !!!注意:

    当调用了save()方法后,对象的变化内容方能持久化至数据库中.

 

1.5.3 获取对象

  Django对象关系映射机制(ORM)基于Queryset.Queryset表示为一个源自数据库的对象集合,其中包含了多个过滤器以对结果进行限制.咱们了解到经过get()方法获取数据库中的单一对象,并利用Post.objects.get()访问该方法.相应的,每一个Django模型至少包含一个管理器,且默认管理器称做objects.经过模型管理器,用户可获得一个Queryset对象.当从某个表中获取全部的对象时,仅需使用默认对象管理器上的all()方法便可,以下:

all_posts = Post.objects.all()

  上述代码显示了Queryset的建立方式,并返回数据库中的所有对象.注意,该Queryset还没有被执行.Django中的Queryset具备延迟性,仅在强制操做下方得以被执行,这种行为使得Queryset更加高效.若是未将Queryset设置为某个变量,而是直接将其写入python shell中,Queryset的SQL语句将被执行--此处将其强制至输出结果中,以下:

Post.objects.all()

  

  1.使用filter()方法

  当过滤Queryset时,可食用管理器的filter()方法.例如,可利用下列Queryset得到2019年中发布的所有帖子:

Post.objects.filter(publisher__year=2019)

  除此以外,还可经过多个字段进行过滤.例如,可经过包含用户名admin的做者获取发布于2019年的全部帖子,以下:

Post.objects.filter(publisher__year=2019,author__username='admin')

  这至关于构建连接多个过滤器的同一Queryset,以下:

Post.objects.filter(publish__year=2017).filter(author__username='admin')

 

  !!!注意:

    包含字段查找方法的查询操做可采用两个下划线予以构建,如publish__year;但同一标记也可用于相关模型的访问字段,如author__username.

 

  2.使用exclude()方法

  利用过滤器的exclude()方法,可从Queryset中排除特定的结果.例如,可获取标题不包含test的、发布于2019年的所有帖子,以下:

Post.objects.filter(publish__year=2019).exclude(title__startswith='test')

 

  3.使用order_by()方法

  利用管理器的order_by()方法,可经过不一样的字段对结果进行排序.例如,可获取以标题排序的所有对象,以下:

Post.objects.order_by('title')

  这里,默认为升序操做.固然还可经过负号前缀进行降序排序,以下:

Post.objects.order_by('-title')

 

 

  1.5.4 删除对象

  若是但愿删除某个对象,可经过delete()方法在对象实例中执行这一操做,以下:

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

  !!!注意:

    删除对象也会删除ForeignKey对象(on_delete设置为CASCADE)的依赖关系.

 

  1.5.5 评估Queryset

  咱们能够链接多个过滤器到一个Queryset上,在Queryset计算以前并不会访问数据库.Queryset仅在如下场合被计算.

  • 首次迭代时
  • 当对Queryset访问时,如Post.objects.all()[:3]
  • 当对Queryset缓存时
  • 当在Queryset上调用repr()或len()时
  • 当在Queryset上显示调用list()时
  • 当在某个语句中对Queryset进行测试时,如bool()、or、and或者if

 

  1.5.6 建立模型管理器

  如前所述,对象表示为每一个模型的默认管理器(可检索数据库中的所有对象).然而,咱们还可针对模型定义定制管理器.下面将建立定制管理器并检索包含published状态的所有帖子.

  对此,存在两种方式可向模型中添加管理器,即添加额外的管理器方法,或者修改初始管理器Queryset.其中,第一个方法提供了相应的Queryset API,如Post.objects.my_manager();而第二个方法则提供了Post.my_manager.all().该管理器可经过Post.published.all()检索帖子.

  下面编辑models.py文件并添加定制管理器,以下:

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super(PublishedManager,self).get_queryset().filer(status='published')

class Post(models.Model):
    # ...
    objects = models.Manager()  # 默认manager
    published = PublishedManager()  # 定制的manager
 

  管理器的get_queryset()方法返回将被执行的Queryset.咱们将覆写该方法,以在最终的Queryset中包含自定义过滤器.以前曾定义了定制管理器,并将其添加值Post模型中,此处可对其加以使用并执行查询.

  经过如下命令再次启用开发服务器:

python manage.py shell

  此处可利用下列命令检索全部发布的帖子,其对应的标题以test开始

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

相关文章
相关标签/搜索