1.场景
图书馆要整理书籍,一本书里会出现多个人物,现有两个表,一个是book,一个是hero,分别记录书本 信息和人物信息。比如说《神雕侠侣》这本书里有杨过、小龙女、郭襄等人物,这是属于一(book)对多(hero)问题,我们可以把关系存在多的一方,即把外键存在hero表里
2.模型类
class BookInfo(models.Model):
"""图书信息:演示一对多,一方"""
btitle = models.CharField(max_length=20, verbose_name='书名')
bpub_date = models.DateField(verbose_name='发布日期')
bread = models.IntegerField(default=0, verbose_name='阅读量')
bcomment = models.IntegerField(default=0, verbose_name='评论量')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'tb_books' # 自定义数据库表名
def __str__(self):
return self.btitle # 输出该模型数据对象时,只输出书名
class HeroInfo(models.Model):
"""人物信息:演示一对多,多方"""
# 确定性别字段的取值范围
GENDER_CHOICES = ((0, 'female'),(1, 'male'))
# 添加外键是BookInfo
hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='人物所属图书')
hname = models.CharField(max_length=20, verbose_name='人名')
hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息')
is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
class Meta:
db_table = 'tb_heros'
def __str__(self):
return self.hname
2.1 由一到多(查询一本书里所有的人物)
先找到某一本书,然后根据它的模型类小写加“_set.all()”获取所有子集
b = BookInfo.objects.get(id=1) # 找到某一本书
b.heroinfo_set.all() # 模型类小写+“_set.all()”
2.2 由多到一(查询一个人物属于哪本书)
先找到某个人,然后直接取相应的外键字段
h = HeroInfo.objects.get(id=1) # 找到某个人
h.hbook # 之前定义的外键字段
3.related_name
上面的由一取多的方法是通过模型类小写加“_set”获取所有子集,我们还可以使用自定义的方法取值,即指定related_name
class BookInfo(models.Model):
...
class HeroInfo(models.Model):
"""人物信息:演示一对多,多方"""
# 确定性别字段的取值范围
GENDER_CHOICES = ((0, 'female'),(1, 'male'))
# 添加外键是BookInfo
hbook = models.ForeignKey(BookInfo,related_name='subs' on_delete=models.CASCADE, verbose_name='人物所属图书')
...
我们把之前的模型类加上了related_name字段,现在可以就可以使用related_name去取子集了
b = BookInfo.objects.get(id=1) # 找到某一本书
# b.heroinfo_set.all() # 模型类小写+“_set.all()” 原来的写法
b.subs.all() # 模型类小写+“_set.all()”