Django - QuerySets学习笔记

进行查询

通过这个例子来说明如何进行查询的:

from django.db import models

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):              # __unicode__ on Python 2
        return self.name

class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()

    def __str__(self):              # __unicode__ on Python 2
        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):              # __unicode__ on Python 2
        return self.headline

创建对象

为了把数据库表中的数据表示成python对象,Django使用了一个直观的系统:一个model class代表一个数据库表
而用这个类的实例表示数据库表中一条特定的记录

要创建一个对象,实例化模型类的关键字参数,然后调用save()将其保存到数据库中。

假定model文件在 mysite/blog/models.py中

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

他背后执行的就是sql的insert语句,在你明确的调用save()之前,
Django不会访问数据库,需要特别说明的是save()方法没有返回值

保存对象的改动

用save()方法来保存已存在于数据库中的对象的改动
假设一个Blog的实例b5已经被保存在数据库中,这个例子更改了它的名字,并且在数据库中更新它的记录

>>> b5.name = 'New name'
>>> b5.save()

他背后执行的就是sql语句的update语法

保存ForeignKey和ManyToManyField字段

>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

>>> from blog.models import Author
>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)

检索对象

检索所有Entry对象

all_entries = Entry.objects.all()

检索发布日期是2006年的对象 注意用双下划线筛选年份

Entry.objects.filter(pub_date__year=2006)

检索发布日期不是2006年的对象 注意用双下划线筛选年份

Entry.objects.exclude(pub_date__year=2006)

检索标题以What 开头,发布日期在2005-1-30与今天之间的Entry

  • __startwith 很好理解 以什么开头
  • __gte 就是great than and equal 大于等于的缩写
  • 类似的还有__lte 就是less than and equal 小于等于的缩写
>>> Entry.objects.filter(
...     headline__startswith='What'
... ).exclude(
...     pub_date__gte=datetime.date.today()
... ).filter(
...     pub_date__gte=datetime(2005, 1, 30)
... )

每次筛选的结果都是独立的

>>> q1 = Entry.objects.filter(headline__startswith="What")
>>> q2 = q1.exclude(pub_date__gte=datetime.date.today())
>>> q3 = q1.filter(pub_date__gte=datetime.date.today())
  • q1查询集是筛选headline以What 开头的所有Entry
  • q2查询集是q1的子集,满足q1的同时,筛选出除了发布日期大于今天的所有Entry,
    也就是今天之前所有的Entry
  • q3查询集也是q1的子集,满足q1的同时,筛选今天之后的所有Entry

他们彼此之间都是独立的互不影响

还有一点查询集的特性需要说明,就是它很‘懒’,看下面的例子

>>> q = Entry.objects.filter(headline__startswith="What")
>>> q = q.filter(pub_date__lte=datetime.date.today())
>>> q = q.exclude(body_text__icontains="food")
>>> print(q)

看上去查询集访问了3次数据库,事实上直到你要用到他的时候他才开始访问数据库,并且只访问了一次

用get()检索一条数据
想要只查询一条数据的话,get()与filter()的区别是,filter()需要切片,像这样filter()[0]

>>> one_entry = Entry.objects.get(pk=1)

你必须确保他只会查到一条数据,如果没查到,他会抛出DoesNotExist异常,
如果查到了多条数据,他会抛出MultipleObjectsReturned异常,

field__lookuptype=value

>>> Entry.objects.filter(pub_date__lte='2006-01-01')

翻译成SQL语句就是:

SELECT * FROM blog_entry WHERE pub_date <= ‘2006-01-01’;

常用的lookuptype:

exact 精确查询 大小写敏感
iexact 大小写不敏感
contains 相当于LIKE '%foo%' 大小写敏感
icontains  大小写不敏感
startswith
endswith
istartswith
iendswith

多个参数和多个筛选之间的区别:

Blog.objects.filter(entry__headline__contains='Lennon',
        entry__pub_date__year=2008)


Blog.objects.filter(entry__headline__contains='Lennon').filter(
        entry__pub_date__year=2008)

假设有个blog,一个Entry包含Lennon,另一个Entry的pub_date在2008年,
但是没有同时满足名字叫’Lennon’并且发布在2008年的Entry

那么第一个筛选不会返回任何blog,第二个可以筛选到这个blog

count()
aggregate(Avg())
aggregate(Max())
Sum(F(‘price’)/F(‘pages’), output_field=FloatField()))

annotate()

annotate() 应该在filter()前面 如果在后面则会忽略annotate()

Evaluate QuerySet

  • Iteration
  • Slicing
  • Pickling/Caching
  • repr()
  • len()
  • count()
  • list()
  • bool()

QuerySet API

Methods that return new QuerySets

  • filter
  • exclude
  • annotate
  • order_by + -前缀 ?随机排序 如果有2个order_by会忽略前面的
  • reverse
  • distinct 去重
  • values
  • values_list(*fields, flat=False)
  • dates(field, kind, order=’ASC’) kind= “year”, “month” or “day”
  • datetimes(field_name, kind, order=’ASC’, tzinfo=None) “year”, “month”, “day”, “hour”, “minute” or “second”
  • none()
  • all()
  • select_related ForeignKey/OneToOneField 时使用和filter一起使用时顺序无要求 select_related(None)清除关系
  • prefetch_related(*lookups)
  • extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
  • defer
  • only
  • using(alias)
  • select_for_update(nowait=False)
  • raw

Methods that do not return QuerySets

  • get(**kwargs)
  • create(**kwargs)
  • get_or_create(defaults=None, **kwargs)
  • update_or_create(defaults=None, **kwargs)
  • bulk_create(objs, batch_size=None) 批量创建
  • count()
  • in_bulk(id_list) 取一个列表pk的值 返回一个dict 每个pk值对应一个对象实例
  • iterator()
  • latest(field_name=None)
  • earliest(field_name=None)
  • first()
  • last()
  • aggregate(*args, **kwargs)
  • exists()
  • update(**kwargs)
  • exists() 用它来判断存在与否 比循环要快
  • update(**kwargs)
  • delete()

Field lookups

  • exact
  • iexact
  • contains
  • icontains
  • in
  • gt
  • gte
  • lt
  • lte
  • startswith
  • istartswith
  • endswith
  • iendswith
  • range
  • year
  • month
  • day
  • week_day
  • hour
  • minute
  • second
  • isnull
  • search(SQL)
  • regex
  • iregex

Aggregation functions

  • Avg(expression, output_field=None, **extra)
  • Count(expression, distinct=False, **extra)
  • Max(expression, output_field=None, **extra)
  • Min(expression, output_field=None, **extra)
  • StdDev(expression, sample=False, **extra) 标准差
  • Sum(expression, output_field=None, **extra)
  • Variance(expression, sample=False, **extra) 方差

Q()
Prefetch(lookup, queryset=None, to_attr=None)

lookup表达式包含了3个部分

  • Fields part
  • Transforms part
  • A lookup
如果我的文章对你有很大帮助 那么不妨?
0%