1. 外键关系

例子:每个 Blog 里有很多 Entry,每个 Entry 只对应一个 Blog

这时,多的方(Entry)就要设置外键到少的方(Blog)

2. 关联表的相互访问

2.1. 从 “多方” 访问

2.1.1. 访问 Entry 关联的 Blog

  1. >>> e = Entry.objects.get(id=2)
  2. >>> e.blog # 返回关联的Blog对象

如果要修改 e.blog 关联的对象,之后必须 save()

2.1.2. 缓存 Entry 关联的所有一对多关系

再次查询时就不用读取数据库了。

  1. e = Entry.objects.select_related()

2.2. 从 “一方” 访问

2.2.1. 访问 Blog 对应的 Entry

  1. >>> b = Blog.objects.get(id=1)
  2. >>> b.entry_set.all() # entry_set
  3. >>> b.entry_set.count() # 总数

通过 _set 访问关联对象集

2.2.2. 关联对象集的其他方法

2.2.2.1. create(**kwargs)

创建一个新的对象,将它保存并放在关联的对象集中。同时返回新创建的对象

2.2.2.2. add(obj1, obj2, …)

添加指定的模型对象到关联的对象集中

2.2.2.3. remove(obj1, obj2, …)

从关联的对象集中删除指定的模型对象

2.2.2.4. clear()

清空关联的对象集

3. 跨关系查询

3.1. 从 “多方” 查询

3.1.1. 查询 Blog id 为 3 的所有 Entry

  1. >>> Entry.objects.filter(blog__id=3)
  2. >>> Entry.objects.filter(blog__pk=3)
  3. >>> Entry.objects.filter(blog=b) # 使用对象实例
  4. >>> Entry.objects.filter(blog=b.id) # 使用实例的id
  5. >>> Entry.objects.filter(blog=5) # 直接使用id

这五种方式都是可以的

3.1.2. 查询 Blog name 为 Beatles 的所有 Entry

  1. Entry.objects.filter(blog__name='Beatles')

返回哪个对象,就用哪个对象的 ModelName.objects.filter()

3.2. 从 “一方” 查询

3.2.1. 查询 Entry headline 包括 Lennon 的所有 Blog

  1. Blog.objects.filter(entry__headline__contains='Lemmon')

3.2.2. 查询 Entry headline 包括 Lennon 且 pub_date 是 2008 的所有 Blog

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

把它分为两个 filter().filter() 就成 OR 了,所以,对于 OR 最好使用Q查询

3.2.3. 查询不包含 Entry headline 包括 Lennon 的和 pub_date 是 2008年的所有 Blog

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

OR,太迷糊用Q查询

3.2.4. 查询不包含 Entry headline 包括 Lennon 且 pub_date 是 2008 的所有 Blog

  1. Blog.objects.exclude(
  2. entry=Entry.objects.filter(
  3. headline__contains='Lennon',
  4. pub_date__year=2008,
  5. ),
  6. )

AND,太迷糊用 Q查询