django中的多表查询以及ForeignKey的相关属性

参考:http://www.cnblogs.com/Finley/p/5537753.html

Django 多表查询

多表查询是模型层的重要功能之一, Django提供了一套基于关联字段独特的解决方案.

ForeignKey

来自Django官方文档的模型示例:

from django.db import models

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

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

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    authors = models.ManyToManyField(Author)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()

class ForeignKey

ForeignKey字段接受一个Model类作为参数, 类型与被参照的字段完全相同:

 blog = models.ForeignKey(Blog)

ForeignKey.to_field

关联到的关联对象的字段名称。默认地,Django 使用关联对象的主键。

blog = models.ForeignKey(Blog, to_field=Blog.name)

ForeignKey.db_constraint

Django Model的ForeignKey字段的主要功能是维护一个一对多的关系, 以进行关联查询.

只有在db_constraint=True时Django model才会在数据库上建立外键约束, 在该值为False时不建立约束.

默认db_constraint=True.

ForeignKey.related_name

这个名称用于让关联的对象反查到源对象.

如果你不想让Django 创建一个反向关联,请设置related_name 为 '+' 或者以'+' 结尾.

ForeignKey.related_query_nameForeignKey.related_name作为默认值, 两者功能的具体说明请参见相关文档

使用ForeignKey查询

前向查询

若关系模型A包含与模型B关联的关联字段, 模型A的实例可以通过关联字段访问与其关联的模型B的实例:

>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

修改e.blog并调用save方法存入数据库

>>> e.blog = some_blog
>>> e.save()

如果ForeignKey 字段有null=True 设置(即它允许NULL值),可以分配None来删除对应的关联性

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Django提供了一种使用双下划线__的查询语法:

>>> Entry.objects.filter(blog__name='Beatles Blog')

反向查询

被索引的关系模型可以访问所有参照它的模型的实例,如Entry.blog作为Blog的外键,默认情况下Blog.entry_set是包含所有参照Blog的Entry示例的查询集,可以使用查询集API取出相应的实例。

>>>b = Blog.objects.get(id=1)
>>>b.entry_set.all()

Entry.blog的related_name和related_query_name可以设置该查询集的名字。

ManyToManyField

来自Django官网的示例:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership', through_fields=('group', 'person'))

class Membership(models.Model):
    group = models.ForeignKey(Group)
    person = models.ForeignKey(Person)
    inviter = models.ForeignKey(Person, related_name="membership_invites")
    invite_reason = models.CharField(max_length=64)
    

class ManyToManyField

ManyToManyField.through

Django 会自动创建一个表来管理多对多关系, 若要手动指定关联表则需要使用through关键字参数.

ManyToManyField.through_fields

上文示例中Membership 有两个外键指向Person (person 和inviter),这使得关联关系含混不清并让Django 不知道使用哪一个。

在这种情况下,必须使用through_fields 明确指定Django 应该使用哪些外键

through_fields 接收一个二元组('field1', 'field2'),其中field1 为指向定义ManyToManyField 字段的模型的外键名称(本例中为group),field2 为指向目标模型的外键的名称(本例中为person).

ManyToManyField.db_table

默认情况下,关联表的名称使用多对多字段的名称和包含这张表的模型的名称以及Hash值生成,如:memberShip_person_3c1f5

若要想要手动指定表的名称,可以使用db_table关键字参数指定.

others

下列API和ForeignKey中的同名API相同.

  • ManyToManyField.db_constraint

  • ManyToManyField.related_name

  • ManyToManyField.related_query_name

使用ManyToManyField查询

多对多关系和ForeignKey具有相似的API.

>>>e = Group.objects.get(id=3)
>>>e.members.all() # Returns all members objects for this Group.

反向查询:

>>>a = Person.objects.get(id=1)
>>>a.group_set.all()

同样related_name可以设置反向查询集的名称。

添加删除关联

因为ManyToManyField自动维护关联表,程序员不便于直接访问.ManyToManyField提供了API用于添加和删除关联(即through表中的记录).

使用一个自动维护through表的模型作为示例:

class User(models.Model):
    user_id = models.IntegerField(primary_key=True)
    
class Flight(models.Model):
    flight_id = models.IntegerField(primary_key=True)
    reserve = models.ManyToManyField(User, related_name='flight_reserve')
    

首先获得要进行关联的Flight和User实例:

flights = Flight.objects.filter(flight_id=flight_id)
if flights.count() != 0:    
    flight = flights[0]
users = User.objects.filter(id=user_id)
if users.count() != 0:
    user = users[0]

通过拥有关联字段的Flight实例进行添加关联操作:

flight.reserve.add(user)
flight.save()

删除操作与这类似:

flight.reserve.remove(user)
flight.save()

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个使用 ForeignKey 字段进行联查询的例子: 假设我们有两个模型,一个是 Book(书籍)模型,另一个是 Publisher(出版社)模型,它们之间通过外键建立了一对多的关系。也就是说,一个出版社可以出版多本书,但一本书只能属于一个出版社。 ```python from django.db import models class Publisher(models.Model): name = models.CharField(max_length=100) city = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=100) publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE) ``` 现在,我们想要查询所有出版社位于纽约的书籍。我们可以使用双下划线语法来查询关联模型的属性,如下所示: ```python books = Book.objects.filter(publisher__city='New York') ``` 在这个查询,我们使用了双下划线语法来查询 Book 模型所有出版社位于纽约的书籍。首先,我们在 publisher 后面使用双下划线来访问 Publisher 模型的属性。然后,我们使用 city='New York' 来查询所有位于纽约的出版社。最后,我们将查询结果存储在 books 变量。 您还可以通过多级关联查询来访问更深层次的关联模型。例如,如果我们想要查询所有姓氏为 Smith 的作者的出版社位于纽约的书籍,可以使用以下查询: ```python books = Book.objects.filter(authors__name__startswith='Smith', authors__book__publisher__city='New York') ``` 在这个查询,我们通过 authors__book__publisher__city 来访问 Publisher 模型的 city 属性。这样,我们就可以查询所有姓氏为 Smith 的作者的出版社位于纽约的书籍。 希望这个例子可以帮助您理解 Django 使用 ForeignKey 进行联查询。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值