zoukankan      html  css  js  c++  java
  • Django模型系统——ORM表结构对应关系

    对于数据库来说一般表结构只会有三种对应关系,分别是一对一、一对多和多对一,下面分别介绍:

    1.一对多

    何为一对多,例如一个学生只可能有一个班级,一个班级却又多个学生,班级表和学生表就是一对多的关系。

    在查询信息的时候有两种方式:正向查询和反向查询。

    (1)正向查询

    复制代码
    models.Student.objects.first()
    <Student: Student object>#返回一个学生对象
    models.Student.objects.first().sname  #可以查询学生信息
    '科比'
    models.Student.objects.first().cid  #由于有关联,可以直接获取班级对象
    <Class: Class object>
    models.Student.objects.first().cid.cname  #查询班级属性
    '全栈6期'
    models.Student.objects.first().cid.first_day
    datetime.date(2017, 7, 14)
    复制代码

    (2)反向查询

    复制代码
    models.Class.objects.filter(id=3)
    <QuerySet [<Class: Class object>]>
    #这是一个班级Queryset
    
    models.Class.objects.filter(id=3)[0]
    <Class: Class object>
    #获取班级对象
    
    models.Class.objects.filter(id=3)[0].cname
    '全栈8期'
    #既然是对象就可以查看相关属性
    
    models.Class.objects.filter(id=3)[0].student_set
    <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x0000019A6A928FD0>
    #反向查找学生,获取学生集合,这是Django自己的模式
    
    models.Class.objects.filter(id=3)[0].student_set.all()
    <QuerySet [<Student: Student object>, <Student: Student object>]>
    #查看集合中所有的对象
    
    models.Class.objects.filter(id=3)[0].student_set.all().values()
    <QuerySet [{'id': 8, 'sname': '小鸟', 'cid_id': 3}, {'id': 11, 'sname': '大爷', 'cid_id': 3}]>
    #可以进一步查看相关属性
    复制代码

    注意:

    如果不在外键的字段中设置related_name的话,默认就用表名_set.

    如果设置了related_name=“students”,反向查找时可以直接使用student进行反向查找。

    >>> class_obj.students.all() 
    #直接获取班级中的学生,而不需要set

    2.一对一

    表结构设计

    复制代码
    class Student(models.Model):
        id = models.AutoField(primary_key=True)
        sname = models.CharField(max_length=32)
        cid = models.ForeignKey("Class")
        detail = models.OneToOneField(to="StudentInfo", null=True)
    
    class StudentInfo(models.Model):
        height = models.CharField(max_length=4)
        weight = models.CharField(max_length=4)
        addr = models.CharField(max_length=32,null=True)
    复制代码

    (1)正向查询

    复制代码
    models.Student.objects.first()
    <Student: Student object>
    #获得一个对象
    
    models.Student.objects.first().detail.addr
    '罗田'
    #正向查询获取属性,通过关联字段直接找
    复制代码

    (2)反向查询

    复制代码
    models.StudentInfo.objects.filter(height=180)
    <QuerySet [<StudentInfo: StudentInfo object>]>
    #获得一个Queryset
    
    models.StudentInfo.objects.filter(height=180)[0].student
    <Student: Student object>
    #反向查找学生,返回一个对象
    
    models.StudentInfo.objects.filter(height=180)[0].student.sname
    '小鸟'
    #查看学生信息
    复制代码

    3.多对多

    1)创建多对多的对应关系有三种方法:

    (1)通过外键创建

    复制代码
    class Class(models.Model):
        id = models.AutoField(primary_key=True)  # 主键
        cname = models.CharField(max_length=32)  # 班级名称
        first_day = models.DateField()  # 开班时间
    
    
    class Teacher(models.Model):
        tname = models.CharField(max_length=32)
    
    
    # 自定义第三张表,通过外键关联上面两张表
    class Teacher2Class(models.Model):
        teacher = models.ForeignKey(to="Teacher")
        the_class = models.ForeignKey(to="Class")
    
        class Meta:
            unique_together = ("teacher", "the_class")  #指定联合唯一
    复制代码

    (2)通过ManyToManyField创建

    复制代码
    class Class(models.Model):
        id = models.AutoField(primary_key=True)  # 主键
        cname = models.CharField(max_length=32)  # 班级名称
        first_day = models.DateField()  # 开班时间
    
    
    class Teacher(models.Model):
        tname = models.CharField(max_length=32)
        # 通过ManyToManyField自动创建第三张表
        cid = models.ManyToManyField(to="Class", related_name="teachers")
    复制代码

    这种方法会自动生成一张对应表,但是不能使用多对多的众多方法。

    (3)通过外键和ManyToManyField创建

    复制代码
    class Class(models.Model):
        id = models.AutoField(primary_key=True)  # 主键
        cname = models.CharField(max_length=32)  # 班级名称
        first_day = models.DateField()  # 开班时间
    
    
    class Teacher(models.Model):
        tname = models.CharField(max_length=32)
        # 通过ManyToManyField和手动创建第三张表
        cid = models.ManyToManyField(to="Class", through="Teacher2Class", through_fields=("teacher", "the_class"))
    
    
    class Teacher2Class(models.Model):
        teacher = models.ForeignKey(to="Teacher")
        the_class = models.ForeignKey(to="Class")
    
        class Meta:
            unique_together = ("teacher", "the_class")
    复制代码

    貌似这种方法最为靠谱,但是最麻烦。

    2)查询的方法

    (1)正向查询(由老师表查询班级)

    复制代码
    models.Teacher.objects.first()
    <Teacher: Teacher object>
    #获取一个老师的对象
    
    models.Teacher.objects.first().cid
    <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x000001FE3916A518>
    #获取老师所对应的班级
    
    models.Teacher.objects.first().cid.all()
    <QuerySet [<Class: Class object>, <Class: Class object>]>
    #获取所有班级对象
    
    models.Teacher.objects.first().cid.all().values()
    <QuerySet [{'id': 1, 'cname': '全栈6期', 'first_day': 
    datetime.date(2017, 7, 14)}, {'id': 3, 'cname': '全栈8期', 'first_day': datetime.date(2017, 10, 17)}]>
    #查看所有值
    复制代码

    为什么能够直接找到班级?

    答案是:通过关联字段

    (2)反向查询(由班级表反向查询老师表)

    复制代码
    models.Class.objects.first()
    <Class: Class object>
    #获取班级对象
    
    models.Class.objects.first().teachers
    <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x000001FE3918C390>
    
    models.Class.objects.first().teachers.all().values()
    <QuerySet [{'id': 1, 'tname': '爱根'}, {'id': 4, 'tname': '日天'}, {'id': 6, 'tname': '银角大王'}]>
    #由班级反向查老师
    
    models.Class.objects.first().teachers.all()
    <QuerySet [<Teacher: Teacher object>, <Teacher: Teacher object>, <Teacher: Teacher object>]>
    复制代码

    刚才正向查找的时候,是因为老师表种由cid这个字段,所以可以直接查找,但是现在这个是怎么关联上的了?请看下面

    cid = models.ManyToManyField(to="Class", related_name="teachers")

    关联的时候设置了related_name,所以可以反向查找。

    注意:这里不能使用teacher_set这种方式,而在一对多种可以使用

    来看看各种对应关系的正向查找:

    复制代码
    #一对多正向查找(学生表——》班级表)
    models.Student.objects.first().cid
    
    #一对一正向查找(学生表——》学生信息表)
    models.Student.objects.first().detail.addr
    
    
    #多对多正向查找(老师表到班级表)
    models.Teacher.objects.first().cid.all()
    
    #正向查找是表中必须有的字段
    复制代码

    来看看各种对应关系的反向查找:

    反向查找是相对于正向查找来说的。

    #一对多反向查找(班级表——》学生表)
    models.Class.objects.filter(id=3)[0].student_set.all()
    
    #一对一反向查找(后面直接可查属性)(学生信息表——》学生表)
    models.StudentInfo.objects.filter(height=180)[0].student
    
    #多对多反向查找(班级表——》老师表)
    models.Class.objects.first().teachers.all()
  • 相关阅读:
    poj 1286 Necklace of Beads poj 2409 Let it Bead HDU 3923 Invoker <组合数学>
    大圣降妖录破解
    dex文件格式二
    dex文件格式一
    打造smali代码库辅助分析
    一键调试脚本使用手册
    TraceView进行性能分析
    Android Killer工具用法
    十三. JEB破解三
    十二. 一步步破解JEB 2.0demo版二
  • 原文地址:https://www.cnblogs.com/yangmingxianshen/p/8344151.html
Copyright © 2011-2022 走看看