Django之Model关系

前言

本文记录个人对Django三种模型关系(一对一,一对多,多对多)理解,由于日后回顾,若有不同意见欢迎批评指正。
软件版本:Django2.2,python3.7

一对一关系(OneToOneField)

Django中使用OneToOneField来进行一对一关系约束,其本质是通过外键关联数据,并设置unique来保证一对一。具体例子如下:

from django.db import models

class Husband(models.Model):
	h_name = models.CharField(max_length=20)

class Wife(models.Model):
	w_name = models.CharField(max_length=20)
	married_man = models.OneToOneField(Husband, null=True, on_delete=models.SET_NULL)

妻子与丈夫就是一个常见的一对一关系,关于上诉例子有两点需要特殊说明的。

1. 主从表关系

由于在Wife中声明了OneToOneField,因此Wife为从表,Husband为主表,在其他类型中也是如此,在那个表中声明了对应关系,那么该表就是从表。

2. on_delete 有五种常用的选项
2.1 models.CASCADE(默认选项)

若设置on_delete=models.CASCADE,或不设置on_delete,当Wife关联的Husband被删除时,Wife也会被一同删除,反之,Husband不会被删除。

2.2 models.PROTECT

保护选项,设置该选项后,若要删除Husband的数据,且该数据关联Wife中的数据,此时系统会报错提示数据受保护,反之可以正常删除。

2.3 models.SET_NULL

空值选项,设置该选项后,若要删除Husband的数据,且该数据关联Wife中的数据,可正常删除,且Wife不会被删除,此时会把Wife的关联数据设置为空,注意使用此选项时必须设置null=True(允许空值),否则会出现异常。

2.4 models.SET_DEFAULT

默认值选项,该选项与SET_NULL类似,当删除与Wife绑定的Husband时,会把Wife的关联数据设置为默认值,注意使用此选项时必须设置Default=你设置的默认值,否则会出现异常。

2.5 models.SET()

该选项与2.3,2.4讲述的选项类似,当删除与Wife绑定的Husband时,会把Wife的关联数据设置为括号内的值,注意防止设置的值与其他设置冲突

3. 主从表间的数据访问

从表可以通过属性名(married_man)访问主表的数据,主表可以通过关联表的表名(wife)获取从表数据,如下:

from django.test import TestCase
from .models import Husband, Wife

class SeModelTests(TestCase):

    def test_one2one(self):
        hus = Husband.objects.create(h_name='h')
        wi = Wife.objects.create(w_name='w', married_man=hus)
        self.assertEqual(wi.married_man.h_name, 'h')
        self.assertEqual(hus.wife.w_name, 'w')
一对多关系(ForeignKey)

Django中的一对多关系,就是通过外键关联两个表,具体例子如下:

from django.db import models

class Grades(models.Model):
	g_name = models.CharField(max_length=20)

class Students(models.Model):
	s_name = models.CharField(max_length=20)
	grade = models.ForeignKey(Grades, on_delete=models.CASCADE)

学生与年级也是常见的一对多的关系,一个年级对应多个学生,若年级被删除了,那对应的学生也不存在,因此设置年级为主表,学生为副表。

主从表间的数据访问

与一对一相同的是:从表可以通过属性名(grade)访问主表的数据。不同之处在于主表可以通过关联表的表名(student)+_set获取从表数据,其中表明_set也是Manager的一个子类,同objects一样有get,filter等方法,具体如下:

from django.test import TestCase
from .models import Grades, Students


class SeModelTests(TestCase):

    def test_one2many(self):
        g = Grades.objects.create(g_name='g1')
        s1 = Students.objects.create(s_name='s1', grade=g)
        s2 = Students.objects.create(s_name='s2', grade=g)
        self.assertEqual(g.students_set.get(pk=1).s_name, 's1')
        self.assertEqual(s1.grade.g_name, 'g1')
多对多关系(ManyToManyField)

Django中通过新建一个记录表的方式来进行多对多数据的关联,实例如下:

from django.db import models

class People(models.Model):
	p_name = models.CharField(max_length=20)

class Things(models.Model):
	t_name = models.CharField(max_length=20)
	grade = models.ManyToManyField(People)

人与事是常见的多对多关系,一个人有多个事要完成,一件事也可以由多个人完成。

主从表间的数据访问

多对多关系中,主表与从表间访问数据的方法都与一对多中,主表访问从表的方式类似,都通过Manager的子类来进行访问,其中主表使用的子类命名规则为从表表明_set(thing_set),从表使用的子类就是对应属性名(worker)具体如下:

from django.test import TestCase
from .models import People, Things


class SeModelTests(TestCase):

    def test_many2many(self):
        p1 = People.objects.create(p_name='p1')
        p2 = People.objects.create(p_name='p2')
        t1 = Things()
        t1.t_name = 't1'
        t1.save()
        t2 = Things()
        t2.t_name = 't2'
        t2.save()
        t1.worker.add(p1, p2)
        p1.things_set.add(t2)
        self.assertEqual(p1.things_set.get(pk=t2.id).t_name, 't2')
        self.assertEqual(t1.worker.get(pk=p1.id).p_name, 'p1')
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值