[Django笔记3]数据库之关联对象

一些废话:

本人大二,最近上了Web开发课,以学习django为主。

首先是觉得对开发有兴趣,另外感觉django的知识比较零碎,所以开创了[Ylxn的Django上课笔记]栏目。所有内容都仅个人学习总结用,毕竟初学会有很多问题,如有错误欢迎指出,感激不尽!

接上期[Django笔记2]模型和表达式-CSDN博客

 多对一关系

首先在model.py添加如下代码

class banj(models.Model):
    mc = models.CharField(max_length=8)
    def __str__(self):
        return self.mc

class xues(models.Model):
    xm = models.CharField(max_length=8)
    bj = models.ForeignKey(banj,on_delete=models.CASCADE,null=True) #外键,关联班级
    def __str__(self):
        return "%s %s" %(self.xm,self.bj)

可以看到:我们建立了两个数据库,

一个是banj(班级);

一个是xues(学生),并且与banj外连接

这样就建立了一个最简单的多对一关系:一个班级可以对应对多个学生,但是一个学生只能在一个班级里面,(我们下面还会介绍多对多关系);

然后django是需要手动在终端执行数据库迁移指令的,需要非常熟悉

python manage.py makemigrations
python manage.py makemigrate

现在我们给刚刚创建的班级和学生两个数据库加入实例变量

(myvenv) D:\mytest\chapter4\chapter4>python manage.py shell
Python 3.9.2 (tags/v3.9.2:1a79785, Feb 19 2021, 13:44:55) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from faqs.models import *
>>> b3 = banj(mc='3班') #创建banj类的对象,未保存
>>> x3 = xues(xm='wangwu',bj=b3) #创建x3,并且引用了没有保存的实例变量b3
>>> x3.save() 
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "D:\mytest\myvenv\lib\site-packages\django\db\models\base.py", line 778, in save
    self._prepare_related_fields_for_save(operation_name="save")
  File "D:\mytest\myvenv\lib\site-packages\django\db\models\base.py", line 1093, in _prepare_related_fields_for_save
    raise ValueError(
ValueError: save() prohibited to prevent data loss due to unsaved related object 'bj'.

尝试保存x3时发生了报错,是因为x3外连接的实例变量b3没有保存,我们保存b3再试试:

>>> b3.save()
>>> x3.save()

刷新一下数据库看看效果:

用代码看一下班级里的学生:

>>> b = banj.objects.get(id=1)
>>> b
<banj: 1班>
>>> b.xues_set.all()
<QuerySet [<xues: zhangsan 1班>]>

以一班为例,我们看见一班中只有一个学生 zhangsan

代码中,b代表1班,

xues_set.all()代表列举所有学生的集合,如果不加all实际上就是一个对象

>>> x3=b.xues_set.create(xm='HanMeimei') 
>>> x3.id,x3.xm
(4, 'HanMeimei')

这里和以前明显不同的地方在于没有写x3.save()

而且数据库也是更新好了的:

 使用object或者set都是直接作用于数据库,而普通的
x3 = xues(xm='ylxn',bj=b)
是一种python语言,x3是python语言中的一种类,这样才需要save

可以通过学生对象来访问关联的班级对象,我们通过班级来创建学生

>>> b                                  
<banj: 1班>
>>> xx = b.xues_set.create(xm='XiaoDeng')
>>> xx.id,xx.xm,xx.bj.id,x3.bj.mc
(6, 'XiaoDeng', 1, '2班')
add调用方法:
>>> b2.xues_set.add(xx)
>>> xx.id,xx.xm,xx.bj.id,x3.bj.mc
(6, 'XiaoDeng', 2, '2班')

班级是学生的外键,可以通过学生对象访问关联的班级对象,通过班级b创建学生xx

b.xues_set用于访问关联对象的模型管理器

调用add()方法创建关系/更改原本的关系

从结果上看:学生XiaoDeng从创建的1班编程了2班

remove删除关系:

再看一下xues数据库的定义:

class xues(models.Model):
    xm = models.CharField(max_length=8)
    bj = models.ForeignKey(banj,on_delete=models.CASCADE,null=True) #外键,关联班级
    def __str__(self):
        return "%s %s" %(self.xm,self.bj)

这里需要强调一下:

1:如果要用到remove,创建数据库的时候,必须要加上null = True,否则会发生如下报错:

django.db.utils.IntegrityError: NOT NULL constraint failed: faqs_xues.bj_id

这是因为:只有在把ForeignKey字段的null选项设置为True时,才允许删除关系

2:banj实例对象和xues实例对象必须要是同一类型,换句话说,我们这里用到的类型有两种,一种是数据库里的对象,一种是python里的对象,如果对象类型不一致也会报错:

AttributeError: 'RelatedManager' object has no attribute 'remove'

我们可以在终端输入下面代码来查看类型

实例名字__dict__

 好的,下面是删除的代码:

>>> from faqs.models import *
>>> b2 = banj.objects.get(id=2)
>>> b2
<banj: 2班>
>>> xx = xues.objects.get(id=6)
>>> xx
<xues: XiaoDeng 2班>
>>> b2.xues_set.remove(xx)

删除关系后,,除了指定数据被改成null,之前其他的数据都会被保留

还可以通过clear()方法来清空指定的所有数据,规则同上

>>> b2.xues_set.clear()

这里b2就是二班,执行以后二班里所有的学生,他们的外键班级全部会变成<null>

多对多关系 

这里我们在models里添加了新的数据库:

class shet(models.Model):
    mc = models.CharField(max_length=8)
    def __str__(self):
        return self.mc

class stus(models.Model):
    xm = models.CharField(max_length=8)
    shets = models.ManyToManyField(shet)
    def __str__(self):
        return self.xm

给数据库创建实例:

(myvenv) D:\mytest\chapter4\chapter4>python manage.py migrate
  Apply all migrations: admin, auth, contenttypes, faqs, sessions
Python 3.9.2 (tags/v3.9.2:1a79785, Feb 19 2021, 13:44:55) [MSC v.1928 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from faqs.models import *
>>> s1 = shet(mc='rds')
>>> s1.save()
>>> s2= shet(mc='wxs')
>>> s2.save()
>>> s3 = shet.objects.create(mc='dms')

使用模型构造函数或者create()方法创建学生对象,接着,我们给社团创建关系关联社团

>>> x1.shets.add(s1,s2)
>>> x1.shets.add(s3)
>>> x1.shets.add(s2)

通过学生对象来创建社团对象:

>>> x2 = stus.objects.create(xm='LiuMing')
>>> x2.shets.all()
<QuerySet []>
>>> x2.shets.create(mc='sgs')
<shet: sgs>
>>> x2.shets.all()
<QuerySet [<shet: sgs>]>

我们先创建了一个新的学生x2,名字交LiuMing,然后通过shets.all()方法可以看到,还没有跟任何社团有管理,所有set为空;

然后用create创建社团sgs,并且与x2建立关联;

再查看关联,就能看见二者已经建立了关联了!

py版本:3.9.2

pycharm:专业版2023.3.3

总结到这里结束,如果你是路人,很感谢你能看到这里,有问题欢迎交流!

  • 27
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值