Django中的一对一、一对多、多对多

  • 一对一

创建两个模型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表结构:

Django中的一对一、一对多、多对多_第1张图片

person表结构:

 Django中的一对一、一对多、多对多_第2张图片

 从表中可以看到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表中数据:

 2019010919114426.png

idcard:

20190109191235153.png

可以看到关联成功了。

当我们在创建一个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('以成功删除!')

删除后数据为:

Django中的一对一、一对多、多对多_第3张图片

Django中的一对一、一对多、多对多_第4张图片

可以看到随着删除卡号106的卡,人也随之删除。

当删除人时:删除名为刘圆圆的人

def delete_person(request):
    name = request.GET.get('name')
    person = Person.objects.get(name=name)
    person.delete()
    return HttpResponse('删除成功')

person表数据:

Django中的一对一、一对多、多对多_第5张图片

idcard表数据:

Django中的一对一、一对多、多对多_第6张图片

可以看到当删除名为刘圆圆的人时,人删除了,但是对应的卡则不会删除。

总结:一对一关系可以两个模型中任意一个指定属性为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

表结构:

teacher表20190109195816428.png

student表 20190109195848954.png

 可以看到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表(数据时原有的): 

20190109202451683.png

student表:

20190109202522256.png

再添加多个学生:

Django中的一对一、一对多、多对多_第7张图片

可以看到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:

Django中的一对一、一对多、多对多_第8张图片

teacher:

20190109203634987.png

可以看到对主表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:

Django中的一对一、一对多、多对多_第9张图片

student:

Django中的一对一、一对多、多对多_第10张图片

可以看到都是空空如也。

总结:

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中的一对一、一对多、多对多_第11张图片

可以看到,Django为我们创建了中间表,完成了多对多的关系映射。这个关系映射也是需要我们自己维护的。当各自添加男生女生时,可以自行添加不进行关系关联。如果男生和女生是朋友则需要进行关联。如下:

先添加一些数据:

Django中的一对一、一对多、多对多_第12张图片

Django中的一对一、一对多、多对多_第13张图片

Django中的一对一、一对多、多对多_第14张图片

此时没有进行关联,中间表是空的。接下来关联一条数据。

如果男生一和女生一是朋友就进行关联:

视图函数:

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=女生一

看看表数据:

20190109213807841.png

可以看到在中间表中通过主键将两个对象关联到了一起。现在使他们都成为朋友:

Django中的一对一、一对多、多对多_第15张图片

可以看到中间表中形成了多对多的关系。一列维护着一方的主键,使之关联到了一起。仔细看,实际上是多对一对多的关系,或者称为两个一对多的关系。

当删除时:

删除一个男生:

 

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表:

Django中的一对一、一对多、多对多_第16张图片

Django中的一对一、一对多、多对多_第17张图片

可以看到中间表中关于男生一的数据都被删除了。

删除一个女生:

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=女生一

删除之后看看表中数据:

女生表:

Django中的一对一、一对多、多对多_第18张图片

中间表:

Django中的一对一、一对多、多对多_第19张图片

可以看到,当删除女生时,与之对应的中间表的数据都没有了。

总结:多对多关系在定义模型时,可以在任何一方建立一个维持关系的属性(girl_boy = models.ManyToManyField(BoyFriend)),Django会自动根据模型完成多对多关系的映射,即创建出中间表。这个关系需要我们自己维护,当需要添加关系时,可以通过关系属性的add方法进行关系关联(gril.girl_boy.add(boy))。多对多没有主从的关系,是由中间表维护的多对多的关系,实际上可以看做是多对一对多,或者两个一对多。当删除数据时,任何一方删除数据,与之对应的中间表数据都会进行删除(相当于一对多的级联删除)。

 

你可能感兴趣的:(大杂烩,Django,一对一,一对多,多对多)