当使用Django进行数据库操作时,ForeignKey(外键)是一种非常有用的字段类型。它允许在数据库表之间创建关联关系,类似于其他数据库系统中的外键概念。通过ForeignKey字段,我们可以建立一个模型与另一个模型的一对多关系。
以下是一个实际例子,使用ForeignKey字段在Django中创建一对多关系,初学者可以通过这个实际例子去仔细观察数据表“一对多”关系是怎么一回事儿。
假设我们正在开发一个博客应用程序,其中有两个主要的模型:作者(Author)和文章(Post)。一个作者可以有多篇文章,而一篇文章只能由一个作者撰写。在这种情况下,我们可以使用ForeignKey字段将文章与作者关联起来。
首先,让我们创建Author模型和Post模型:
from django.db import models
# Create your models here.
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
writer = models.ForeignKey(Author, on_delete=models.CASCADE)
def __str__(self):
return self.title
在上述代码中,我们定义了Author模型和Post模型。Post模型中的writer
字段是一个ForeignKey字段,它将Post模型与Author模型相关联。on_delete=models.CASCADE
参数表示当关联的作者被删除时,与该作者关联的所有文章也将被删除。
接下来,我们可以使用这些模型创建数据库表:
python manage.py makemigrations
python manage.py migrate
现在我们已经创建了Author和Post表,我们用下面的代码来演示数据表“一对多”关系的操作及对数据表的影响。
import os
import django
# 设置Dango运行时需要的环境变量DJANGO_SETTINGS_MODULE
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings')
# 加载Django的设置
django.setup()
# 导入模型
from app1.models import Author, Post
# 创建一个作者
author1 = Author(name='wenhao')
author1.save()
# 创建一篇文章,并将其与刚才创建的作者相关联
post1 = Post(title='First Post', content='Hello, World!', writer=author1)
post1.save()
# 再创建一篇文章,也将其与刚才创建的作者相关联
post2 = Post(title='My love', content='I love wang hong', writer=author1)
post2.save()
# 获取一个作者的所有文章
author_get = Author.objects.get(name='wenhao')
posts_all = author_get.post_set.all()
for post in posts_all:
print(post)
在上面的代码中,作者“wenhao”发表了两篇文章,文章的title分别为’First Post’和’My love’,通过Post模型的一对多成员writer关联到表 Author。
如果要理解语句posts_all = author_get.post_set.all()
中的post_set(),请参看我的另一篇博文,链接:https://blog.csdn.net/wenhao_ir/article/details/131668597
上面的代码运行结果如下:
可见作者“wenhao”对应的两篇文章的标题被打印出来了。
这里要多问一句,为什么内容没被打印出来呢?
请注意数据表模型中定义的下面语句:
def __str__(self):
return self.title
并结合Python的“魔术方法“(magic method)或“特殊方法“(special method)去理解这个问题,关于Python的“魔术方法“(magic method)或“特殊方法“(special method),请参见链接:https://blog.csdn.net/wenhao_ir/article/details/131395984
我们再去观察一下数据表中的内容,如下:
大家可以仔细观察下这两张表的内容,看下Author是怎样和Post进行一对多关联的。
从上面的数据库截图中可以看出,在表 app1_post中,外键字段的名字为 writer_id,而不是想像中的 writer,这一点要注意,其值就是作者wenhao在表app_author中的id字段。
显然,光凭数据表里的数据,是无法知道字段表 app1_post中的writer_id是指向表app_author中的数据,Django肯定在另外的地方记录下了这种对应关系,记录下这种对应关系的表叫“中间关系表”,这个“中间关系表”并没有在数据库中,目前昊虹君也不知道具体在哪里。不过在Django的某个地方,肯定存在着一个“中间关系表”,它的内容如下:
writer_set→Author
提问:_set 是怎么来的?
答:从writer映射到模型Author 的关系在数据库中叫做反向关系,writer_set称为反向关系名,即related_name,如果不指定反向关系名,统就会以"字段名_set"的格式作为其默认反向关系名。
显然,如果模型中,有多个“一对多”或“多对多”关系时,相应的字段名不能相同,否则会引起冲突。为什么?举个例子,假如另一个模型中也有一个一对多的关系,这个一对多的关系指向模型Book,但是这个一对多的关系的字段名也为writer,那么“中间关系表”中就会存在一条下面这样的反向关系记录:
writer_set→Book
所以,“中间关系表”的内容如下:
writer_set→Author
writer_set→Book
这样,通过中间关系表就无法分清楚到底是哪个writer与Author模型相对应,又是哪个writer与Book模型相对应。
如果不能避免字段名字的相同,就要使用相关名称参数(related_name)来为其在中间关系表中指定反向关系名,比如:
writer = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='blogs_writer')
writer = models.ForeignKey(Book, on_delete=models.CASCADE, related_name='book_writer')
经上面的两条代码指定反向关系名,便没有冲突了。
并且用related_name参数指定反向关系名后,就可以用这个反向关系名来访问相应的字段了,比如下面这个示例:
# 获取一个作者的所有文章
author_get = Author.objects.get(name='wenhao')
posts_all = author_get.blogs_writer.all()
for post in posts_all:
print(post)
运行上面的代码,可得到下面的结果:
在建立一对多关系或多对多关系时,建议大家指定不容易重复的反向关系名,这样可以提高代码的健壮性。文章来源:https://www.toymoban.com/news/detail-519853.html
扩展阅读:
Django中使用反向关系名称(related_name)解决由“多对多”关系引起的字段名字冲突问题引起的迁移命令报错。文章来源地址https://www.toymoban.com/news/detail-519853.html
到了这里,关于通过一个实际例子说明Django中的数据库操作方法法ForeignKey()的用法【数据表“一对多”关系】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!