zoukankan      html  css  js  c++  java
  • Django ORM

    查询对象

    Django 中查询数据库需要 Manager 和 QuerySet 两个对象。从数据库里检索对象,可以通过模型的 Manage 来建立 QuerySet,一个 QuerySet 表现为一个数据库中对象的结合,他可以有0个一个或多个过滤条件,在 SQL里 QuerySet 相当于 select 语句用 where 或 limit 过滤。你通过模型的 Manage 来获取 QuerySet。

    Manager

    Manager 对象附在模型类里,如果没有特指定,每个模型类都会有一个 objects 属性,它构成了这个模型在数据库所有基本查询。

    Manager 的几个常用方法:

    • all:返回一个包含模式里所有数据库记录的 QuerySet
    • filter:返回一个包含符合指定条件的模型记录的 QuerySet
    • exclude:和 filter 相反,查找不符合条件的那些记录
    • card = Card.objects.filter(pk=offline_card_id).get()
      card = Card.objects.exclude(pk=offline_card_id).get() 相反的两条语句
    • get:获取单个符合条件的记录(没有找到或者又超过一个结果都会抛出异常)
    • order_by:改变 QuerySet 默认的排序

    QuerySet 类

    QuerySet 接受动态的关键字参数,然后转换成合适的 SQL 语句在数据库上执行。

    QuerySet 的几个常用方法:

    • distinct
    • values
    • values_list
    • select_related
    • filter:返回一个包含符合指定条件的模型记录的 QuerySet
    • extra:增加结果集以外的字段

    字段过滤

    字段查找是指定 SQL 语句的 WHERE 条件从句,通过 QuerySet 的方法 filter()exclude() 和 get() 指定查询关键字。

    格式为:field__lookuptype=value

    lookuptype 有以下几种:

    • gt : 大于
    • gte : 大于等于
    • in : 包含
    • lt : 小于
    • lte : 小于等于
    • exact
    • iexact
    • contains:包含查询,区分大小写
    • icontains:不区分大小写
    • startswith:匹配开头
    • endswith:匹配结尾
    • istartswith:匹配开头,不区分大小写
    • iendswith:匹配结尾,不区分大小写
    使用 Extra 调整 SQL
    
    用extra可以修复QuerySet生成的原始SQL的各个部分,它接受四个关键字参数。如下:
    
    select:修改select语句
    where:提供额外的where子句
    tables:提供额外的表
    params:安全的替换动态参数
    增加结果集以外的字段:
    
    queryset.extra(select={'成年':'age>18'}) 
    提供额外的 where 条件:
    
    queryset.extra(where=["first like '%小明%' "])
    提供额外的表:
    
    queryset.extra(tables=['myapp_person'])
    安全的替换动态参数:
    F 关键字参数
    
    前面给的例子里,我们建立了过滤,比照模型字段值和一个固定的值,但是如果我们想比较同一个模型里的一个字段和另一个字段的值,django 提供 F()——专门取对象中某列值的操作。
    
    >>> from django.db.models import F
    >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))
    当然,还支持加减乘除和模计算:
    
    >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
    >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))
    >>> 
    >>> Entry.objects.filter(authors__name=F('blog__name'))
    对于日期类型字段,可以使用 timedelta 方法:
    
    >>> from datetime import timedelta
    >>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
    还支持位操作 .bitand() 和 .bitor():
    
    >>> F('somefield').bitand(16)
    主键查找
    
    Django 支持使用 pk 代替主键:
    
    >>> Blog.objects.get(id__exact=14) # Explicit form
    >>> Blog.objects.get(id=14) # __exact is implied
    >>> Blog.objects.get(pk=14) # pk implies id__exact
    pk 还可以用于其他的查找类型:
    
    # Get blogs entries with id 1, 4 and 7
    >>> Blog.objects.filter(pk__in=[1,4,7])
    
    # Get all blog entries with id > 14
    >>> Blog.objects.filter(pk__gt=14)
    
    >>> Entry.objects.filter(blog__id__exact=3) # Explicit form
    >>> Entry.objects.filter(blog__id=3)        # __exact is implied
    >>> Entry.objects.filter(blog__pk=3)        # __pk implies __id__exact
    Q 关键字参数
    
    QuerySet 可以通过一个叫 Q 的关键字参数封装类进一步参数化,允许使用更复杂的逻辑查询。其结果 Q对 象可以作为 filter 或 exclude 方法的关键字参数。
    
    例子:
    
    from django.db.models import Q
    Q(question__startswith='What')
    支持 & 和 | 操作符:
    
    Q(question__startswith='Who') | Q(question__startswith='What')
    上面的查询翻译成 sql 语句:
    
    WHERE question LIKE 'Who%' OR question LIKE 'What%'
    取反操作:
    
    Q(question__startswith='Who') | ~Q(pub_date__year=2005)
    也可以用在 filter()、exclude()、get() 中:
    
    Poll.objects.get(
        Q(question__startswith='Who'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )
    翻译成 sql 语句为:
    
    SELECT * from polls WHERE question LIKE 'Who%'
        AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
    删除对象
    >>>entry = Entry.objects.get(pk=1)
    >>>entry.delete()
    >>>Blog.objects.all().delete()
    
    >>>Entry.objects.filter(pub_date__year=2005).delete()
    关系对象
    当对象之间存在映射关系或者关联时,该如何查询呢?
    
    当你在模型里定义一个关系时,模型实例会有一个方便的 API 来访问关系对象。以下分几种映射关系分别描述。
    
    One-to-many关系
    
    如果一个对象有ForeignKey,这个模型实例访问关系对象通过简单的属性:
    
    >>> e = Entry.objects.get(id=2)
    >>> e.blog # Returns the related Blog object.
    你可以凭借外键属性获取和赋值,修改外键值知道执行 save() 方法才会保存到数据库:
    
    >>> e = Entry.objects.get(id=2)
    >>> e.blog = some_blog
    >>> e.save()
    如果关联的对象可以为空,则可以将关联对象职位 None,删除关联:
    
    >>> e = Entry.objects.get(id=2)
    >>> e.blog = None
    >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"
    子查询:
    
    >>> e = Entry.objects.get(id=2)
    >>> print(e.blog)  # Hits the database to retrieve the associated Blog.
    >>> print(e.blog)  # Doesn't hit the database; uses cached version.
    也可以使用 select_related() 方法,该方法会提前将关联对象查询出来:
    
    >>> e = Entry.objects.select_related().get(id=2)
    >>> print(e.blog)  # Doesn't hit the database; uses cached version.
    >>> print(e.blog)  # Doesn't hit the database; uses cached version.
    你也可以通过 模型_set 来访问关系对象的另一边,在 Blog 对象并没有维护 Entry 列表,但是你可以通过下面方式从 Blog 对象访问 Entry 列表:
    
    >>> b = Blog.objects.get(id=1)
    >>> b.entry_set.all() # Returns all Entry objects related to Blog.
    
    # b.entry_set is a Manager that returns QuerySets.
    >>> b.entry_set.filter(headline__contains='Lennon')
    >>> b.entry_set.count()
    模型_set 可以通过 related_name 属性来修改,例如将 Entry 模型中的定义修改为:
    
     blog = ForeignKey(Blog, related_name='entries')
    上面的查询就会变成:
    
    >>> b = Blog.objects.get(id=1)
    >>> b.entries.all() # Returns all Entry objects related to Blog.
    
    # b.entries is a Manager that returns QuerySets.
    >>> b.entries.filter(headline__contains='Lennon')
    >>> b.entries.count()
    Many-to-many关系
    
    e = Entry.objects.get(id=3)
    e.authors.all() # Returns all Author objects for this Entry.
    e.authors.count()
    e.authors.filter(name__contains='John')
    
    a = Author.objects.get(id=5)
    a.entry_set.all() # Returns all Entry objects for this Author.
    One-to-one关系
    
    class EntryDetail(models.Model):
        entry = models.OneToOneField(Entry)
        details = models.TextField()
    
    ed = EntryDetail.objects.get(id=2)
    ed.entry # Returns the related Entry object.
    当反向查询时:
    
    e = Entry.objects.get(id=2)
    e.entrydetail # returns the related EntryDetail object
    这时候如果没有关联对象,则会抛出 DoesNotExist 异常。
    
    并且还可以修改:
    
    e.entrydetail = ed
    参考资料
    Making queries
    Eclipse的django开发学习笔记(2)--模型(M)
    Django:模型的使用
    django orm总结

    参考文章网址:http://blog.javachen.com/2015/01/15/django-orm/

  • 相关阅读:
    Linux文件系统的层级结构
    3.求m+mm+mmm+…+m…m(n个)的和,其中m为1~9之间的整数。 例如,当m=3、n=4时,求3+33+333+3333的和。
    编写一个Java程序,计算一下1,2,…,9这9个数字可以组成多少个互不相同的、无重复数字的三位偶数。
    抽象类和抽象方法
    定义一个“点”(Point)类用来表示三维空间中的点(有三个坐标)。要求如下: (1)可以生成具有特定坐标的点对象。 (2)提供可以设置三个坐标的方法。 (3)提供可以计算该“点”距原点距离平方的方法。 (4)编写主类程序验证。
    (1)定义一个接口CanFly,描述会飞的方法public void fly(); (2)分别定义类飞机和鸟,实现CanFly接口。 (3)定义一个测试类,测试飞机和鸟,在main方法中创建飞机对象和鸟对象, 再定义一个makeFly()方法,其中让会飞的事物飞。并在main方法中调用该方法, 让飞机和鸟起飞。
    (1)定义一个接口Compute含有一个方法int computer(int n,int m); (2)设计四个类分别实现此接口,完成+-*/运算 (3)设计一个类UseCompute,含有方法: public void useCom(Compute com, int one, int two) (4)设计一个测试类
    完成Adventure中的主方法
    中国特色社会主义的体制中有这样的现象:地方省政府要坚持党的领导和按 照国务院的指示进行安全生产。请编写一个java应用程序描述上述的体制现象。
    (1)编写一个接口:InterfaceA,只含有一个方法int method(int n); (2)编写一个类:ClassA来实现接口InterfaceA,实现int method(int n)接口方 法时,要求计算1到n的和; (3)编写另一个类:ClassB来实现接口InterfaceA,实现int method(int n)接口 方法时,要求计算n的阶乘(n!); (4)编写测试类E测试
  • 原文地址:https://www.cnblogs.com/blogofwyl/p/4376474.html
Copyright © 2011-2022 走看看