• 08 django模型系统(三)--表关系的实现与一对多关联表的数据操作


    表关系实现

    1. 表关系的创建
    - OneToOne  创建一个学生详情表StudentDetail,与Student表一对一关系

    student = models.OneToOneField('Student', on_delete=models.CASCADE)

    - OneToMany

    grade = models.ForeignKey('Grade', on_delete=models.SET_NULL, null=True)

    - ManyToMany

    学生表(Student)与课程表(Course)之间是多对多的关系,通过中间表关联。中间表分别去外键关联,并且联合唯一

    详细model.py如下:

    from django.db import models
    # Create your models here.
    
    class Student(models.Model):
        name = models.CharField(max_length=20)
        age = models.SmallIntegerField(default=0)
        sex = models.SmallIntegerField(default=1)
        qq = models.CharField(max_length=20,unique=True,null=True)
        phone = models.CharField(max_length=20,unique=True,null=True)
        #删除年级的时候不必把学生都删除,必须可以设置年级字段为null,on_delete=models.SET_NULL,null=True
        grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True)   #一对多关系,与Grade是多对一的关系
        c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
        e_time = models.DateTimeField(verbose_name='编辑时间',auto_now=True)
        is_deleted = models.BooleanField(default=False)
        def __str__(self):
            return '%s-%s-%s' %(self.id,self.name,self.age)
    
    class StudentDetail(models.Model):
        num = models.CharField(max_length=20,default="")
        college = models.CharField(max_length=20,default="")
        #如果把学生删除了,学生详情里面的也要删除on_delete=models.CASCADE(级联操作,保证一直)
        student = models.OneToOneField('Student',on_delete=models.CASCADE)   #与Student表一对一关系,‘Student’字符串更加通用,无论Student模型是在前面后者后面都能使用
     
    class Grade(models.Model):
        name = models.CharField(max_length=20)
        num = models.CharField(max_length=20)
    
        def __str__(self):
            return '%s - %s' %(self.num,self.name)
    
    class Course(models.Model):
        name = models.CharField('课程名称',max_length=20)
        students = models.ManyToManyField('Student',through='Enroll')#与学生是多对多,如果中间表只有两个表的id,则不需要主动创建中间表Enroll,系统自动创建中间表teacher_course_students
        def __str__(self):                                          #如果第三张表中有额外的字段,需要手动创建中间表Enroll
            return self.name
    
    class Enroll(models.Model):  #中间表为报名表
        student = models.ForeignKey('Student',on_delete=models.CASCADE) #中间表分别去外键关联,并且联合唯一
        course = models.ForeignKey('Course',on_delete=models.CASCADE)
        pay = models.FloatField('缴费金额',default=0)
        c_time = models.DateTimeField('报名时间',auto_now_add=True)

    2. 关联表的数据操作

    一对多关系操作

    - OneToMany
    - 正向: 一个模型如果定义了一个外键字段,通过这个模型操作外键
    增删改查

    导入模型,并查看已经创建的数据表数据

    In [2]: from teacher.models import Student,StudentDetail,Course,Enroll,Grade                                                                                                                                          
    
    In [3]: Grade.objects.all()                                                                                                                                                                                           
    Out[3]: <QuerySet [<Grade: 33期 - django框架>, <Grade: 34期 - 爬虫>]>
    
    In [4]: Student.objects.all()                                                                                                                                                                                         
    Out[4]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>]>

    正向增加的两种方法:

    #1.第一种 通过直接赋值一个已经保存的对象给她
    In [5]: s= Student() In [6]: s.name='梦洁' In [7]: g1 = Grade.objects.first() #g1为Grade的对象 In [8]: s.grade = g1 #Grade表必须先创建,不然保存不能成功 In [9]: s.save() In [10]: Student.objects.all() Out[10]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>, <Student: 3-梦洁-0>]>
    #2.第二种。赋值给他一个已经保存的Id给他
    In [11]: s2 = Student(name = '魏明凯') In [12]: g2 = Grade.objects.last() In [13]: s2.grade_id =g2.id In [14]: s2.save() #Grade必须首先创建 In [15]: Student.objects.all() Out[15]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>, <Student: 3-梦洁-0>, <Student: 4-魏明凯-0>]>

    正向更新修改:

    In [34]: Student.objects.all()                                                                                                                                                                                       
    Out[34]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>, <Student: 3-梦洁-0>, <Student: 4-魏明凯-0>, <Student: 5-litao-0>]>
    
    In [35]: s2= Student.objects.get(id=2)                                                                                                                                                                                                                                                                                                                                                                                          
    
    In [36]: s2                                                                                                                                                                                                          
    Out[36]: <Student: 2-litao-0>
    
    In [37]: s1= Grade.objects.first()                                                                                                                                                                                   
    
    In [38]: s2.grade=s1                                                                                                                                                                                                 
    
    In [39]: s2.save()   

    正向删除:
    删除外键时候定义必须有一个None

    grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True)
    In [41]: s= Student.objects.first()                                                             
    
    In [42]: s                                                                                      
    Out[42]: <Student: 1-心蓝-0>
    
    In [43]: s.grade= None                                                                          
    
    In [44]: s.save()   

    正向查:

    通过学生表的查询学生所在班级的名称,班级

    In [41]: s= Student.objects.first() 
    In [49]: s.grade.name 
    Out[49]: 'django框架'
    
    In [50]: s.grade.num 
    Out[50]: '33期'

    反向:

    从Grade的对象反过来查和它 关联的student的模型
    一个模型如果被另外一个模型外键关联,通过这个模型去对关联它的模型进行操作就叫反向

    反向增加

    1.直接创建,增加
    In [53]: g3 =Grade.objects.create(name='进阶',num='40期') #反向,g3.反向关联字表的小写_set 操作 In [54]: g3.student_set.create(name='刘洋') Out[54]: <Student: 6-刘洋-0> #2.将已经存在的对象添加到g3,add,create都是立刻执行,不需要save() In [55]: s Out[55]: <Student: 1-心蓝-0> In [56]: g3.student_set.add(s)

     反向查询

    In [81]: g3.student_set.all()                                                                                                                                                                                         
    Out[81]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>, <Student: 6-刘洋-0>]>
    
    In [82]: s3.grade                                                                                                                                                                                                     
    Out[82]: <Grade: 40期 - 进阶>

    反向修改更新:

    #s3 本来是33期,通过反向查询将其修改为40期
    #add方法可以添加多个对象#g3.student_set.add(s3,s2,s1)
    In [78]: s3 = Student.objects.get(id=2)                                                                                                                                                                               
    
    In [79]: s3.grade                                                                                                                                                                                                     
    Out[79]: <Grade: 33期 - django框架>
    
    In [80]: g3.student_set.add(s3)                                                                                                                                                                    

    反向删除:

    In [89]: g3.student_set.all()                                                                                                                                                                                         
    Out[89]: <QuerySet [<Student: 1-心蓝-0>, <Student: 2-litao-0>, <Student: 6-刘洋-0>]>
    
    In [90]: s.name                                                                                                                                                                                                       
    Out[90]: '心蓝'
    
    In [91]: g3.student_set.remove(s)                                                                                                                                                                                     
    
    In [92]: g3.student_set.all()                                                                                                                                                                                         
    Out[92]: <QuerySet [<Student: 2-litao-0>, <Student: 6-刘洋-0>]>

    反向清除:clear

    In [95]: g3.student_set.all()                                                                                                                                                                                         
    Out[95]: <QuerySet [<Student: 2-litao-0>, <Student: 6-刘洋-0>]>
    
    In [96]: g3.student_set.clear()                                                                                                                                                                                       
    
    In [97]: g3.student_set.all()                                                                                                                                                                                         
    Out[97]: <QuerySet []>

    反向修改重置:

    In [98]: s                                                                                                                                                                                                            
    Out[98]: <Student: 1-心蓝-0>
    
    In [100]: s1= Student.objects.get(id=2)                                                                                                                                                                               
    
    In [101]: g3.student_set.set([s,s1])    #接受一个列表,先调用clear,在添加add。如果没有clear再执行add

    查询student 表中所有的django框架的学生

    In [109]: res = Student.objects.filter(grade__name='django框架')    #关联字段用'__'
    In [110]: print(res.query) SELECT `teacher_student`.`id`, `teacher_student`.`name`, `teacher_student`.`age`, `teacher_student`.`sex`, `teacher_student`.`qq`, `teacher_student`.`phone`, `teacher_student`.`grade_id`, `teacher_student`.`c_time`, `teacher_student`.`e_time` FROM `teacher_student` INNER JOIN `teacher_grade` ON (`teacher_student`.`grade_id` = `teacher_grade`.`id`) WHERE `teacher_grade`.`name` = django框架
  • 相关阅读:
    Mybatis 动态sql(转载)
    mapper映射文件配置之select、resultMap(转载)
    mapper映射文件配置之insert、update、delete(转载)
    MyBatis主配置文件(转载)
    函数装饰器和闭包(二)
    函数装饰器和闭包(一)
    指针的指针(二)
    指针的指针(一)
    Makefile基础(三)
    Python之多线程与多进程(二)
  • 原文地址:https://www.cnblogs.com/taoge188/p/10506447.html
Copyright © 2020-2023  润新知