概述
一对多模型类关系
-
新建两个应用:User、Article
-
Usermodel.py
from django.db import models # 定义用户模型 class User(models.Model): username = models.CharField(max_length=100)
-
Articlemodels.py
from django.db import models from users.models import User # 定义分类模型 class Category(models.Model): name = models.CharField(max_length=100) # 定义文章模型 class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # 分类外键 category = models.ForeignKey('Category',on_delete=models.CASCADE) # 作者外键 author = models.ForeignKey(User,on_delete=models.CASCADE,null=True)
一对多的外键,定义在多的一方:一个分类有多个文章,外键定义在文章模型。
-
数据库迁移
>>> python manage.py makemigrations >>> python manage.py migrate
-
添加数据:
Python Console
>>> from users.models import User >>> from article.models import Article, Category # 新建用户 >>> Jack = User(username="Jack") >>> Jack.save() # 新建分类 >>> python = Category(name="python") >>> python.save() # 新建文章 >>> art = Article( title='Django实战', content='Django', category=Category.objects.first(), author=User.objects.first() ) >>> art.save() # 获取文章模型数据 >>> Article.objects.first() <Article: Article object (1)> >>> a = Article.objects.first() >>> a.title 'Django实战'
-
当业务需要获取某一分类模型(Category)下的所有文章,则:
Python Console
# 获取id为1的分类模型 >>> category = Category.objects.get(pk=1) # 获取该分类下的所有文章(<引用模型的模型名转化为小写_set>) >>> articles = category.article_set.all() >>> articles <QuerySet [<Article: Article object (1)>]>
一对多模型关系中,会自动生成一个字段在"一"的一方:
该字段命名:<引用模型的模型名转化为小写_set>,
该字段可以根据模型类外键中的
related_name
参数进行自定义,如下:category = models.ForeignKey('Category',related_name="articles")
注意:赋值了
related_name
参数,默认的xx_set
字段将不能使用。 -
还有一种不常见的添加数据方式:
Python Console
>>> category = models.Category.objects.get(pk=1) >>> article = Article(title='test',content='test') >>> article.author = User.objects.first() >>> # aritcle.save() >>> category.article_set.add(article) >>> category.save()
当运行上面代码的时候,就会报错如下:
<Article: Article object (None)> instance isn't saved.Use bulk=False or save the object first.
大概意思就是
artilce
这个这个实例还没有被保存,需要先进行保存。所以先执行如上注释处:
acticle.save()
,此时又分为两种情况:- 如果设置了
catagory
值可以为空,正常保存 - 如果设置了
catagory
值不可以为空,将会报错,此时就陷入了死循环中,需要借助bulk
参数。如下:
>>> category = models.Category.objects.get(pk=1) >>> article = Article(title='test',content='test') >>> article.author = User.objects.first() >>> category.article_set.add(article, bulk=True)
使用了
bulk
参数,Django会自动保存所有实例。 - 如果设置了
一对一模型类关系
应用场景:
在实际网站中,可能需要保存用户的许多信息,但是有些信息是不经常用的。如果把所有信息都存放到一张表中可能会影响查询效率,因此可以把用户的一些不常用的信息存放到另外一张表中我们叫做UserExtension。用户表User与该表UserExtension就是典型的一对一了。
-
Usermodel.py
from django.db import models # 用户模型 class User(models.Model): username = models.CharField(max_length=200) # 用户信息模型 class UserExtension(models.Model): school = models.CharField(max_length=100) user = models.OneToOneField('User',on_delete=models.CASCADE)
-
数据库迁移
>>> python manage.py makemigrations >>> python manage.py migrate
-
添加数据:
Python Console
>>> from users.models import User, UserExtension >>> user = User.objects.first() >>> ex = UserExtension(school='yizhong') >>> ex.user = user >>> ex.save() >>> user.userextension.school 'yizhong'
一对一模型关系中,字段定义在任何一方即可,会自动生成一个字段
该字段可以根据模型类外键中的
related_name
参数进行自定义,如下:user = models.OneToOneField('User',related_name='extension')
注意:赋值了
related_name
参数,默认的字段将不能使用。
多对多模型类关系
应用场景:
比如文章和标签的关系。一篇文章可以有多个标签,一个标签可以被多个文章所引用。因此标签和文章的关系是典型的多对多的关系。
实现方式:
Django为这种多对多的实现提供了专门的Field。叫做
ManyToManyField
。
-
Articlemodels.py
class Tag(models.Model): name = models.CharField(max_length=100) # 定义多对多字段 articles = models.ManyToManyField('Article') class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() category = models.ForeignKey('Category', on_delete=models.CASCADE) author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
多对多字段在两个模型中随便一个添加外键即可。
-
数据库迁移
>>> python manage.py makemigrations >>> python manage.py migrate
打开navicat查看映射进去的数据表,因为我们创建了一个模型
Tag
,数据库会新增一张表article_tag
,但还发现新增了一张表article_tag_articles
,该表的结构如下:三个字段,一个是id主键,另外两个都是外键,一个参考
article_article
这个表,另外一个参考article_tag
这个表,该表是Django默认生成的,以此实现多对多关系。 -
添加数据
>>> from books.models import Tag >>> art = Article.objects.first() >>> tag = Tag(name="hot") >>> art.tag_set.add(tag) # 报错如下:
ValueError: Cannot add "<Tag: Tag object (None)>": instance is on database "default", value is on database "None"
大意是没有办法对Article添加这个标签,因为Tag标签里面还没有信息,也就是我们还没有对Tag中的信息进行保存。这个时候我们可以使用一下
bluk
参数,如下:>>> from books.models import Tag >>> art = Article.objects.first() >>> tag = Tag(name="hot") >>> art.tag_set.add(tag,bluk=False) # 报错如下:
TypeError: add() got an unexpected keyword argument 'bluk'
没有
bluk
这个参数。注意:一对多的时候可以使用
bluk
,多对多没有这个bluk
参数。所以需要先保存标签实例对象:
>>> from books.models import Tag >>> art = Article.objects.first() >>> tag = Tag(name="hot") >>> tag.save() >>> art.tag_set.add(tag) >>> art.tag_set.all() >>> <QuerySet [<Tag: Tag object (1)>]> >>> t = art.tag_set.first() >>> t.name 'hot' # 如此,保存成功。
tag_set
这个属性,同上可以根据related_name
这个参数来自定义。
最后
以上就是开朗老虎为你收集整理的不同模型类关系的ORM操作的全部内容,希望文章能够帮你解决不同模型类关系的ORM操作所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复