如何在Django中进行表关联?附models.py代码示例
嘿,看了你的models代码,我来帮你捋捋Django里数据表关联的常见操作——你的Topic和Question是一对多关联,Topic又和User是一对多关联,下面是具体的操作示例,都是日常开发里常用的:
这是最常用的场景,不管是从主表查子表,还是从子表回溯主表都很方便:
从Topic获取关联的所有Question:
你给Question的外键字段topic设置了related_name='question',所以直接通过这个关联名就能拿到某个主题下的所有问题:# 先获取一个Topic实例 topic = Topic.objects.get(name="Python基础") # 获取该主题下的所有问题 questions = topic.question.all() # 遍历输出问题名称 for q in questions: print(q.name)从Question回溯所属的Topic:
直接访问Question实例的topic字段就行,Django会自动帮你关联到对应的Topic对象:question = Question.objects.get(name="什么是装饰器?") # 获取该问题所属的主题 topic = question.topic print(topic.name, topic.description)从User获取其创建的所有Topic:
你的Topic里created_by设置了related_name='topic',所以用这个关联名就能拿到用户创建的所有主题:from django.contrib.auth.models import User user = User.objects.get(username="vinoth") # 获取该用户创建的所有主题 user_topics = user.topic.all()
创建Question的时候,需要把它关联到已有的Topic,有两种常见方式:
直接指定外键字段:
# 先获取要关联的Topic target_topic = Topic.objects.get(name="Django进阶") # 创建Question并关联该Topic new_question = Question.objects.create( name="如何优化Django查询性能?", img="optimize_query.png", topic=target_topic, created_by=request.user # 假设当前登录用户是创建者 )通过Topic的关联名直接创建:
这种方式更简洁,不用单独保存Question,Django会自动处理关联:target_topic = Topic.objects.get(name="Python基础") # 通过Topic的related_name直接创建关联的Question target_topic.question.create( name="列表和元组的区别是什么?", img="list_tuple.png", created_by=request.user )
如果需要把某个Question的所属Topic改成另一个,直接修改外键字段再保存就行:
question = Question.objects.get(name="什么是装饰器?") new_topic = Topic.objects.get(name="Python进阶") question.topic = new_topic question.save()
默认情况下,Django外键的on_delete参数是CASCADE——也就是说,如果你删除了一个Topic,所有关联这个Topic的Question都会被一起删除。如果你想改变这个行为,可以在定义外键的时候调整参数,比如:
# 比如删除Topic后,Question的topic字段设为null(需要先给topic字段加null=True) topic = models.ForeignKey(Topic, related_name='question', on_delete=models.SET_NULL, null=True)
举个删除的例子:
old_topic = Topic.objects.get(name="过时主题") old_topic.delete() # 默认情况下,所有关联这个Topic的Question都会被删除
对了,你的Question模型里created_by字段好像没写完,记得补全哦,比如:
created_by = models.ForeignKey(User, related_name='created_questions', on_delete=models.CASCADE)
内容的提问来源于stack exchange,提问作者vinoth kumar

