• Django学习笔记之model篇(三)-- 表关系及多表查询


    表关系的建立

    建立学院信息表、学生信息表、课程表、学生详情表,
    表关系如下:

    学院信息表    《= 一对多  ForeignKeyField   =》  学生信息表
    
    学生信息表 《= 一对一  OneToOneField =》 学生详细信息表
    
    课程表      《= 多对多  ManyToManyField =》学生信息表

    在model中建立以下几个模型类:

    # models.py
    from django.db import models
    
    # 学院表
    class Department(models.Model):
        d_id = models.AutoField(primary_key=True)
        d_name = models.CharField(max_length=30)
    
        def __str__(self):
            return "Department<d_id=%s,d_name=%s>"%(self.d_id,
                                                    self.d_name)
    
    # 学生表
    class Student(models.Model):
        s_id = models.AutoField(primary_key=True)
        s_name = models.CharField(max_length=30)
        department = models.ForeignKey('Department',
                                       null=True, #可以为空值
                                       related_name='student', # 反向查询用(就不_set了:d1.student_set.all() -》d1.student )
                                       on_delete=models.CASCADE)   # 外键,自动关联表的主键 级联删除
    
        def __str__(self):
            return "Student<s_id=%s, s_name=%s,department_id=%s >"%(self.s_id,
                                                                    self.s_name,
                                                                    self.department_id)
    
    # 学生选课表
    class Course(models.Model):
        c_id = models.AutoField(primary_key=True)
        c_name= models.CharField(max_length=30)
        student = models.ManyToManyField('Student',
                                         related_name='course',
                                         ) # 多对多   生成第三张关系表
    
        def __str__(self):
            return "Course<c_id=%s,c_name=%s,student=%s>"%(self.c_id,
                                                           self.c_name,
                                                           self.student)
    
    # 学生详情表
    class Stu_detail(models.Model):
        s_id = models.OneToOneField('Student',on_delete=models.CASCADE)  # 一对一, 级联删除
        s_age = models.IntegerField()
        gender = models.BooleanField(default=1)
        city = models.CharField(max_length=30)
    
        def __str__(self):
            return "s_id=%s,s_age=%s,s_gender=%s"%(
                                                self.s_id,
                                                self.s_age,
                                                self.gender
            )

    执行完makemigrations 和migrate之后,会发现生成了5张表,这是因为ManyToManyField关系生成了5第三张关系表。

    python manage.py shell 我们进入项目的目录,进入IDLE操作演示数据库的操作语句更方便:

    1.进入IDLE
    2.查看当前的目录路径
    3.导入我们项目中的模型类

    一对多表关系数据的添加:

    往数据表student中添加数据的第一种方式:

    s1 = Student(s_name='xiaoming',department_id=1)
    s1.save()

    往数据表student中添加数据的第二种方式:

    # 先在Department里面创建一条数据d1再进行操作
    s2 = Student(s_name='小红')
    s2.department_id=d1
    s2.save()

    1.第一种方式就是跟之前的一样,用传参的方法添加,需要注意的是外键的值必须是关联表中已经存在的值.
    2.第二种方式是用的属性赋值的方式,因为我们在模型类有定义了一个department的属性,而这个属性的对象的类型必须是department表的类实例对象

    表关联对象的访问:

    s1.department
    #  属性取值,会拿到的=d1
    
    # 通过管理器反向访问
    d1.student_set.all()
    # 在Foreignkey里面设置related_name='student',这样就可以直接用名字而不是_set的形式了
    d1.student.all()
    
    #这个是实例对象
    s1.departmnet
    
    # 下面3个是管理器
    d1.student
    s1.course
    c1.student
    #

    这里写图片描述

    处理关联对象的一些方法:

        # 一对多,多的那头就有这个管理器,就有以下方法
        # 管理器才能用add,create,clear,remove方法
        d1 = Department.objects.get(d_id=1)
        s1 = Student.objects.get(s_id=1)
        c1 = Course.objects.get(c_id=1)
        # print(d1,s1,c1)
        print(d1.student.all()) # 查询到学院的所有学生, 通过一对多关系,管理器.all()
        print(s1.department) # 模型类里面的属性,直接访问
        print(c1.student) # 管理器 多对多
        print(c1.student.all()) # 报名这个课程的学生
        # print(s1.course_set.all()) # 学生报了哪些课, 反向查询,可以用related_name去改
        print(s1.course.all()) # 学生报了哪些课, 反向查询用related_name  管理器
    

    1.add(obj1, obj2, …) 添加的已经存在数据库的数据
    添加一指定的模型对象到关联的对象集中

        ## add 必须是在数据库中存在的对象  :修改
        d1.student.add(s1)    # 将s1学生改成d1学院中
        s1 = Student.objects.filter(s_id=1)
        d1 = Department.objects.filter(d_id=1)  filter取到的是QuerySet,类似于集合形式
        d1[0].student.add(s1[1])  #先拿到某个实例对象
        #例2
        s6 = Student(s_name='大大', department_id=2)
        s6.save()  # 必须保证department字段允许为空
        d1.student.add(s6) #
        s6 = Student.objects.get(s_name='小小')

    2.create(**kwargs) 添加不存在的数据 ,将数据直接存入数据库
    创建一个新的对象,将它保存并放在关联的对象集返回新创建的对象

    s1.course.create(c_name='C语言程序设计') # 会同时向两个表格添加数据
    d1.student.create(s_name='小帅')    # 给d1学院添加一个学生(之前不存在数据库中)

    3.remove(obj1, obj2, …) 从关联的对象集中删除指定的模型对象。
    删除的是关系表中的数据

    s1.course.remove(c1)     # 学生取消某个选修课

    4.clear() 从关联的对象集中删除所有的对象

    注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法

    s1.course.clear()    # 删除的是中间信息表的信息

    多表查询—-跨关联关系的查询:

    Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段:

    # 查询学院名字为‘计算机学院’的学生的信息 
    Student.objects.filter(department__d_name='计算机学院')

    它还可以反向工作。若要引用一个“反向”的关系,只需要使用该模型的小写的名称。

    #查询学生名字中包含 '小' 的学生的学院信息
    Department.objects.filter(student__s_name__contains='小')
    # 查询学号为1的学生所有的课程
    Course.objects.filter(student__s_id=1)
    # 查询报了课程1的所有的学生
    Student.objects.filter(course__c_id=1)
    # 查询报了'python'课程的的学生的所属学院的信息
    Department.objects.filter(student__course__c_name='python')
  • 相关阅读:
    .net Core使用EFCore连接数据库
    前端实践项目(二)webpack生成html和外部引用
    前端实践项目(一)使用webpack进行打包编译
    消息队列的模式
    消息队列的应用场景
    .Net EasyNetQ的使用
    .Net中简单地使用RabbitMQ消息队列
    C# 虚函数virtual的使用之二
    C#之System.Object
    .Net EntityFramework(EF) CodeFirst模式
  • 原文地址:https://www.cnblogs.com/shuai06/p/12397510.html
Copyright © 2020-2023  润新知