zoukankan      html  css  js  c++  java
  • 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')
  • 相关阅读:
    【原创】绝对居中
    MSSQL数据库各角色权限
    如何升级至 XHTML?
    XHTML 语法
    5.4 删除一个元素节点或者文本节点
    Ajax实现无刷新的获取数据并绑定到GridView,以及无刷新更新数据[转]
    鼠标滑过时显示图片内容隐藏和鼠标滑过图片隐藏内容显示的两种小方法
    纯CSS3魔方的制作
    201920201学期 20192415 《网络空间安全专业导论》XOR加密
    201920201学期 20192415 《网络空间安全专业导论》第四周学习总结
  • 原文地址:https://www.cnblogs.com/shuai06/p/12397510.html
Copyright © 2011-2022 走看看