美文网首页
django QuerySet API

django QuerySet API

作者: 高阳刘 | 来源:发表于2017-10-19 14:16 被阅读0次

    Django模型中偶尔我们学到了一些基本的创建也查询。这里专门来讲一下数据库接口相关的接口(QuerySet API)

    从数据库中查询出来的结果一般是一个集合,这个集合叫做QuerySet文中的例子大部分是基于这个blog/models.py

    from django.db import models
    # Create your models here.
    
    class Blog(models.Model):
        name = models.CharField(max_length=100)
        tagline = models.IntegerField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name = models.CharField(max_length=50)
        email = models.TextField()
        
        def __str__(self):
            return self.name
    
    
    class Entry(models.Model):
        blog = models.ForeignKey(Blog)
        headline = models.CharField(max_length=255)
        body_text = models.TextField()
        pub_date = models.DateField()
        mod_date = models.DateField()
        authors = models.ManyToManyField(Author)
        n_comments = models.IntegerField()
        n_pingbacks = models.IntegerField()
        rating = models.IntegerField()
        
        def __str__(self):
            return self.headline
    
    1、QuerySet 创建对象的方法
    In [2]: from people.models import *
    
    In [3]: b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
    
    In [4]: b.save()
    

    总之,一共有四种方法

    方法一:

    In [5]: Author.objects.create(name='liu', email='123@163.com')
    Out[5]: <Author: liu>
    

    方法二:

    In [6]: a = Author(name='gao', email='234@163.com')
    
    In [7]: a.save()
    

    方法三:

    In [8]: a1 = Author()
    
    In [9]: a1.name='yang'
    
    In [10]: a1.email='345@163.com'
    
    In [11]: a1.save()
    

    方法四:

    In [12]: Author.objects.get_or_create(name='ya',email='456@163.com')
    Out[12]: (<Author: ya>, True)
    
    In [13]: Author.objects.get_or_create(name='ya',email='456@163.com')
    Out[13]: (<Author: ya>, False)
    # 首先尝试获取,不存在就创建,可以防止重复
    # 返回值(object,True/False)
    

    备注:前三种方法返回的都是对应的object,最后一种方法返回的是一个元组,(object,True/False),创建时返回True,已存在时返回False
    当有一对多、多对一、或者多对多的关系的时候,先把相关的对象查询出来

    In [27]:entry = Entry.objects.get(id=1)
    
    In [28]: cheese_blog = Blog.objects.get(name='Beatles Blog')
    
    In [29]: entry.blog = cheese_blog
    
    In [30]: entry.save()
    
    2、获取对象的方法
    In [34]: Author.objects.all()  # 查询所有
    Out[34]: <QuerySet [<Author: liu>, <Author: gao>, <Author: yang>, <Author: ya>]>
    
    In [35]: Author.objects.all()[:4]
    Out[35]: <QuerySet [<Author: liu>, <Author: gao>, <Author: yang>, <Author: ya>]>  # 切片操作,获取4个人,不支持负索引,切片可以节约内存,不支持负索引,后面有相应解决办法,第7条
    
    In [36]: Author.objects.get(name='liu')
    Out[36]: <Author: liu>  # 名称为 WeizhongTu 的一条,多条会报错
     
    #get是用来获取一个对象的,如果需要获取满足条件的一些人,就要用到filter
    In [37]: Author.objects.filter(name='liu')
    Out[37]: <QuerySet [<Author: liu>]>  # 等于
    
    In [38]: Author.objects.filter(name__exact='liu')
    Out[38]: <QuerySet [<Author: liu>]>  # 名称为 abc 但是不区分大小写,可以找到 ABC, Abc, aBC,这些都符合条件
     
    In [39]: Author.objects.filter(name__regex='^liu')
    Out[39]: <QuerySet [<Author: liu>]>  # 正则表达式查询
     
    # filter是找出满足条件的,当然也有排除符合某条件的
    In [40]: Author.objects.exclude(name__contains='y')
    Out[40]: <QuerySet [<Author: liu>, <Author: gao>]>  # 排除包含 "y" 的Author对象
    
    In [44]: Author.objects.exclude(email='345@163.com').filter(name__contains='y')
    Out[44]: <QuerySet [<Author: ya>]>  # 找出名称含有"y", 但是排除email是'345@163.com'的
    
    3、删除符合条件的结果

    和上面类似,得到满足条件的结果,然后delete就可以(危险操作,正式场合操作务必慎重),比如:

    In [47]: Author.objects.filter(name__contains='g').delete()
    Out[47]: (2, {'people.Author': 2, 'people.Entry_authors': 0})  # 删除 名称中包含“g”得人
    
    In [48]: Author.objects.filter(name__contains='g').delete()
    Out[48]: (0, {})  # 没有名称中包含”g“的人
    
    In [49]: a = Author.objects.filter(name__contains='g')
    In [50]: a.delete()
    Out[50]: (0, {})  # 写成两条语句也是可以的,效果一样,但是实际上Django只执行了一条SQL语句
    
    4、更新某个内容

    批量更新,适用于all()、filter()、exclude()等后面(危险操作,正式场合操作务必慎用)

    In [64]: Author.objects.filter(name__contains='l').update(name="sansa")
    Out[64]: 2  # 名字中包含“l”得人都改成“sansa” 返回2,说明修改了两条数据
    
    In [65]: Author.objects.filter(name__contains='s')
    Out[65]: <QuerySet [<Author: sansa>, <Author: sansa>]>
    

    单个object更新,适合于.get(),get_or_create(),update_or_create()等得到的obj,和新建很类似。

    In [4]: a = Author.objects.get(name="li")
    
    In [5]: a.name="lil"
    
    In [6]: a.email="111@111.com"
    
    In [7]: a.save()  # 最后不要忘记保存!!!
    
    5、QuerySet 是可迭代的
    In [20]: a = Author.objects.all()
    
    In [21]: for e in a:
        ...:     print(e)
        ...:     
    lil
    ya
    gao
    yang
    

    Author.objects.all() 或者 QuerySet 是查询所有的Author条目。
    注意事项:
    1、如果只检查Author中是否有对象,应该用

    In [22]: Author.objects.all().exists()
    Out[22]: True
    

    2、QuerySet 支持切片,可以节省内存

    In [23]: Author.objects.all()[:2]
    Out[23]: <QuerySet [<Author: lil>, <Author: ya>]>
    

    3、用len(a)可以得到Author的数量,但是推荐用:

    In [24]: Author.objects.count()
    Out[24]: 4
    # 或者用的是SQL:select count(*)
    

    4、list(a)可以强行将QuerySet变成列表

    6、QuerySet是可以用pickle序列化到硬盘在读取出来的
    >>> import pickle
    >>> query = pickle.loads(s)     # Assuming 's' is the pickled string.
    >>> qs = MyModel.objects.all()
    >>> qs.query = query            # Restore the original 'query'.
    
    7、QuerySet 查询结果排序

    作者按照名称排序

    In [27]: Author.objects.all().order_by('name')
    Out[27]: <QuerySet [<Author: gao>, <Author: lil>, <Author: ya>, <Author: yang>]>
    
    In [28]: Author.objects.all().order_by('-name')
    Out[28]: <QuerySet [<Author: yang>, <Author: ya>, <Author: lil>, <Author: gao>]>
    # 在column name 前面加一个负号,可以实现倒序
    
    8、QuerySet 支持链式查询
    In [39]: Author.objects.filter(name__contains='y').filter(email="456@163.com")
    Out[39]: <QuerySet [<Author: ya>]>
    
    9、QuerySet 不支持负索引
    In [56]: Author.objects.all()
    Out[56]: <QuerySet [<Author: lil>, <Author: ya>, <Author: gao>, <Author: yang>]>
    
    In [57]: Author.objects.all().reverse()
    Out[57]: <QuerySet [<Author: lil>, <Author: ya>, <Author: gao>, <Author: yang>]>  # 直接用reverse()并没有起作用
    
    In [58]: Author.objects.all().order_by('name')
    Out[58]: <QuerySet [<Author: gao>, <Author: lil>, <Author: ya>, <Author: yang>]>  # 按照名字排序
    
    In [59]: Author.objects.all().order_by('name').reverse()
    Out[59]: <QuerySet [<Author: yang>, <Author: ya>, <Author: lil>, <Author: gao>]>  # 按照名字排序之后再逆序reverse()正常使用
    
    10、QuerySet 重复问题,使用distinct() 去重

    一般情况下,QuerySet 中不会出来重复问题,重复是很罕见的,但是当跨域多张表进行检索后,结果并到一起,可能会出来重复的值(遇到的问题)

    相关文章

      网友评论

          本文标题:django QuerySet API

          本文链接:https://www.haomeiwen.com/subject/ompsuxtx.html