创建两个模型IdCard和Person实现一对一的关系:
class IdCard(models.Model): card_number = models.IntegerField() class Meta: db_table = 'idcard' class Person(models.Model): name = models.CharField(max_length=32) # 通过将属性设置为OneToOneFieldl类型实现一对一的关系 person_idcard = models.OneToOneField(IdCard) class Meta: db_table = 'person
idcard表结构:
person表结构:
从表中可以看到Django根据person_idcard属性自动生成了外键字段person_idcard_id,使得两张表完成了一对一关系。
在视图中添加一个idcard直接添加就可以:
def add_idcard(request): cardnum = request.GET.get('cardnum') cards = IdCard.objects.filter(card_number=cardnum) if cards.exists(): return HttpResponse('改卡已存在!') card = IdCard() card.card_number = cardnum card.save() return HttpResponse('添加卡成功!')
添加一个person时,因为在Person中定义了 person_idcard ,通过该字段完成了一对一的关系,所以在创建person时,需要指定该属性值,以完成一对一的关系
def add_person(request): name = request.GET.get('name') cardnum = request.GET.get('cardnum') card = IdCard.objects.get(card_number=cardnum) person = Person() person.name = name person.person_idcard = card person.save() return HttpResponse('添加人成功!')
通过请求添加一个Person,并指定对应IdCard
http://localhost:8001/fiveApp/addPerson/?name=成龙&cardnum=106
看看person表中数据:
idcard:
可以看到关联成功了。
当我们在创建一个Person时,将它继续关联到卡号为106时,就会报一下错误:
django.db.utils.IntegrityError: (1062, "Duplicate entry '7' for key 'person_idcard_id'")
删除时:
删除卡号为106的卡:
def delete_idcard(request): cardnum = request.GET.get('cardnum') cards = IdCard.objects.filter(card_number=cardnum) if not cards.exists(): return HttpResponse('该卡不存在!') card = IdCard.objects.get(card_number=cardnum) card.delete() return HttpResponse('以成功删除!')
删除后数据为:
可以看到随着删除卡号106的卡,人也随之删除。
当删除人时:删除名为刘圆圆的人
def delete_person(request): name = request.GET.get('name') person = Person.objects.get(name=name) person.delete() return HttpResponse('删除成功')
person表数据:
idcard表数据:
可以看到当删除名为刘圆圆的人时,人删除了,但是对应的卡则不会删除。
总结:一对一关系可以两个模型中任意一个指定属性为models.OneToOneField类型进行模型关系关联。实际上从表结构看出
一对一关系也是通过建立外键而关联的,实际上也有主从表之分,可以看做一种特殊的一对多关系。维持关系的一方(创建外检的一方)是从表,没有维持关系的一方是主表。当删除从表数据时并不会对从表的数据造成英雄,当删除主表数据时,会删除与之关联的从表数据。这种删除称之为级联删除。但当我们在从表中添加数据时,不能将外键指向已经关联数据的主表数据,否则会报错。
创建teacher和student表,模型为:
class Teacher(models.Model): name = models.CharField(max_length=32) class Student(models.Model): name = models.CharField(max_length=32) # 通过指定外键创建一对多关系 stu_tea = models.ForeignKey(Teacher
表结构:
可以看到Django为我们成功创建了一对多的关系。
添加student需要指定关系(和一对一是进行关联一样):
def add_student(request): tname = request.GET.get('tname') sname = request.GET.get('sname') teachers = Teacher.objects.filter(name=tname) if not teachers.exists: return HttpResponse('该老师不存在!') teacher = Teacher.objects.get(name=tname) student = Student() student.name = sname student.stu_tea = teacher student.save() return HttpResponse('添加学生成功!')
添加一个学生:
http://localhost:8000/fiveApp/addStudent/?tname=雷锋&sname=你
表中数据:
teacher表(数据时原有的):
student表:
再添加多个学生:
可以看到student表中的多条数据同时指向了主键为1的老师,这就形成了一对多的关系。
删除数据时:
删除student数据:删除学生 他
def delete_student(request): name = request.GET.get('name') students = Student.objects.filter(name=name) if not students.exists(): return HttpResponse('该学生不存在!') student = Student.objects.get(name=name) student.delete() return '删除学生成功!'
表数据:
student:
teacher:
可以看到对主表teacher并没有产生影响,只是单单删除了从表中的数据。
删除teacher雷锋:
def delete_teacher(request): name = request.GET.get('name') teachers = Teacher.objects.filter(name=name) if not teachers.exists: return HttpResponse('该老师不存在!') teacher = Teacher.objects.get(name=name) teacher.delete() return HttpResponse('成功删除老师!')
看看表中数据:
teacher:
student:
可以看到都是空空如也。
总结:
Django中的一对多关系通过定义属性为ForeignKey类型而进行关系关联(比如:stu_tea = models.ForeignKey(Teacher)),
定义了这个属性的模型完成从表的映射,另一模型完成主表的映射。可以将从表中的多条数据同时关联到主表中的一条数据,形成一对多的关系。当删除主表数据时,会删除与数据关联的从表中的数据,进行级联删除。
比如一个男生可以有多个女性朋友,一个女生可以有多个男性朋友,形成了多对多的关系(*_*)。如何创建模型?如下:
class BoyFriend(models.Model): name = models.CharField(max_length=32) class GirlFriend(models.Model): name = models.CharField(max_length=32) girl_boy = models.ManyToManyField(BoyFriend)
在GirlFriend中创建了关联属性girl_boy,使Django完成多对多的关系映射。看看所创建的表
可以看到,Django为我们创建了中间表,完成了多对多的关系映射。这个关系映射也是需要我们自己维护的。当各自添加男生女生时,可以自行添加不进行关系关联。如果男生和女生是朋友则需要进行关联。如下:
先添加一些数据:
此时没有进行关联,中间表是空的。接下来关联一条数据。
如果男生一和女生一是朋友就进行关联:
视图函数:
def add_boy_girl(request): bname = request.GET.get('bname') gname = request.GET.get('gname') boys = BoyFriend.objects.filter(name=bname) girls = GirlFriend.objects.filter(name=gname) if not boys.exists(): return HttpResponse('该男生不存在!') if not girls.exists(): return HttpResponse('该女生不存在!') boy = BoyFriend.objects.get(name=bname) gril = GirlFriend.objects.get(name=gname) # 通过关联属性的add()方法进行关联 gril.girl_boy.add(boy) return HttpResponse('成功关联!')
添加关联:
localhost:8000/fiveApp/addBoyGirl/?bname=男生一&gname=女生一
看看表数据:
可以看到在中间表中通过主键将两个对象关联到了一起。现在使他们都成为朋友:
可以看到中间表中形成了多对多的关系。一列维护着一方的主键,使之关联到了一起。仔细看,实际上是多对一对多的关系,或者称为两个一对多的关系。
当删除时:
删除一个男生:
def del_boyfriend(request): name = request.GET.get('name') boys = BoyFriend.objects.filter(name=name) if not boys.exists(): return HttpResponse('该男生不存在!') boy = BoyFriend.objects.get(name=name) boy.delete() return HttpResponse('删除成功!')
删除男生一看看数据:
boyfriend表:
可以看到中间表中关于男生一的数据都被删除了。
删除一个女生:
def del_girlfriend(request): name = request.GET.get('name') girls = GirlFriend.objects.filter(name=name) if not girls.exists(): return HttpResponse('该男生不存在!') girl = GirlFriend.objects.get(name=name) girl.delete() return HttpResponse('删除成功!')
删除女生一:
http://localhost:8000/fiveApp/delGirlFriend/?name=女生一
删除之后看看表中数据:
女生表:
中间表:
可以看到,当删除女生时,与之对应的中间表的数据都没有了。
总结:多对多关系在定义模型时,可以在任何一方建立一个维持关系的属性(girl_boy = models.ManyToManyField(BoyFriend)),Django会自动根据模型完成多对多关系的映射,即创建出中间表。这个关系需要我们自己维护,当需要添加关系时,可以通过关系属性的add方法进行关系关联(gril.girl_boy.add(boy))。多对多没有主从的关系,是由中间表维护的多对多的关系,实际上可以看做是多对一对多,或者两个一对多。当删除数据时,任何一方删除数据,与之对应的中间表数据都会进行删除(相当于一对多的级联删除)。