博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
django模型基础(三)
阅读量:5129 次
发布时间:2019-06-13

本文共 16095 字,大约阅读时间需要 53 分钟。

本文转载自https://blog.csdn.net/xiaogeldx/article/details/88084034

表关系

在这里插入图片描述

在这里插入图片描述

一对一(OneToOne)

  • 通过本表的主键外键关联另一张表的主键
  • 创建张学生详情表(在students的models.py文件中)

    from django.db import models          class Student(models.Model):              name = models.CharField(max_length=20)              age = models.SmallIntegerField(default=0)              gender = models.SmallIntegerField(default=1)              qq = models.CharField(max_length=20,default='')              phone = models.CharField(max_length=20,default='')              c_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)              def __str__(self):                  return '%s-%s' % (self.name, self.age)          class StudentDetail(models.Model):  #学生对学生详情,一对一              num = models.CharField(max_length=20, default='')              college = models.CharField(max_length=20,default='')              #Student最好用字符串               student = models.OneToOneField('Student', on_delete=models.CASCADE)                  #外键和一对一关系的时候需要加on_delete选项,此参数为了避免两个表里的数据不一致问题,不然会报错    #一般使用CASCADE表示级联删除

    图中的student_id就是外键关联

    在这里插入图片描述

    一对多(OneToMany)

    from django.db import models      class Student(models.Model):          name = models.CharField(max_length=20)          age = models.SmallIntegerField(default=0)          gender = models.SmallIntegerField(default=1)          grade = models.ForeignKey('Grade', on_delete=models.SET_NULL, null=True)    #删除某个学生后,班级对应的位置会显示为NULL          qq = models.CharField(max_length=20,default='')          phone = models.CharField(max_length=20,default='')          c_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)          def __str__(self):              return '%s-%s' % (self.name, self.age)      class StudentDetail(models.Model):      #学生对学生详情,一对一          num = models.CharField(max_length=20, default='')          college = models.CharField(max_length=20,default='')          #Student最好用字符串            student = models.OneToOneField('Student', on_delete=models.CASCADE)         class Grade(models.Model):  #学生对班级,一对多          num = models.CharField(max_length=20)          name = models.CharField(max_length=20)

    在这里插入图片描述

    多对多(ManyToMany)

    class Course(models.Model):          name = models.CharField('课程名称', max_length=20)  #参数第一位就是verbose_name,“verbose_name=”可省略          students = models.ManyToManyField('Student', through='Enroll')    #Student表和Course表可以不通过Enrol就能相互访问l#如果只有外键和id两个字段时会自动创建第三张表关联      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)

    在这里插入图片描述

    在这里插入图片描述

    关联表的数据操作

    进入项目目录的idle

  • 为了能方便学习,进入项目的idle去执行操作
  • 通过python manage.py shell就能进入当前目录下的idle
    • 进入idle
    • 查看当前的目录路径
    • 导入我们项目中的模型类

      在这里插入图片描述

      OneToMany

  • 正向:一个模型如果定义了一个外键字段,通过这个模型去操作这个外键就是正向

    In [2]: from students.models import Student,StudentDetail,Grade,Course,Enroll                                                            In [3]: Grade.objects.all()                                                                                                              Out[3]: 
    ,
    ]> In [4]: s = Student() In [5]: s.name = 'xiaoge' In [6]: g1 = Grade.objects.first() In [7]: g1 Out[7]:
    In [8]: s.grade = g1 #增 #方法1 In [9]: s.save() In [10]: s2 = Student(name='na') In [11]: g2 = Grade.objects.last() In [12]: s2.grade_id = g2.id #增 #方法2,效果和方法1一样 In [13]: s2.save() In [18]: s = Student.objects.first() In [21]: s.grade = g2 #改 #grade是定义在模型Student里面的ForeignKey,对它的操作就是正向 #它的修改和普通字段修改没什么区别,赋值然后保存 In [22]: s.grade Out[22]:
    In [24]: s.grade = None #删 In [25]: s.save() In [26]: s = Student.objects.first() In [28]: s.grade #返回值为空#只有外键定义了null=True才能删除,否则不能 In [30]: s2 Out[30]:
    In [31]: s2.grade.name #查 #和属性操作一样 Out[31]: '爬虫' In [33]: s2.grade.num #查 #和属性操作一样 Out[33]: '256期'
  • 反向:

    In [36]: g3 = Grade.objects.create(name='进阶',num='40期')      #如果模型1有一个ForeignKey,那么该ForeignKey所指的模型2实例可以通过一个管理器返回前面有Foreignkey的模型1的所有实例,默认情况下,这个管理器的名字为模型名字的小写+_set                                                                           In [37]: g3.student_set.create(name='long')     #反向增1   #模型名的小写_set 是个管理器 ,是对象的集合                                                                                     Out[37]: 
    In [38]: s = Student.objects.last() In [39]: s.grade.name #查 Out[39]: '进阶' In [40]: s.grade.num Out[40]: '40期' In [47]: s = Student.objects.first() In [49]: g3.student_set.add(s) #增2 #可以一次增多个 In [51]: g3.student_set.all() #查 #student_set在此处的用法相当于objects Out[51]:
    ,
    ]> In [52]: g3.student_set.filter(name='xiaoge') #查 Out[52]:
    ]> In [53]: g3.student_set.filter(name='xiaoge').count() #查 Out[53]: 1 In [54]: g3.student_set.remove(s) #删1 #可以一次删多个 In [55]: g3.student_set.all() Out[55]:
    ]> In [56]: g3.student_set.clear() #删2 清空 In [57]: g3.student_set.all() Out[57]:
    In [58]: g3.student_set.set([s,s2]) #改 #set方法会先调用clear,再添加 (如果没有clear方法,clear不执行,直接添加) In [59]: g3.student_set.all() Out[59]:
    ,
    ]> In [60]: res = Student.objects.filter(grade__name='django框架') In [61]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`gender`, `students_student`.`grade_id`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time` FROM `students_student` INNER JOIN `students_grade` ON (`students_student`.`grade_id` = `students_grade`.`id`) WHERE `students_grade`.`name` = django框架 In [62]: res Out[62]:

    ManyToMany

    In [64]: Course.objects.create(name='python全栈')                                                                                        Out[64]: 
    In [65]: Course.objects.create(name='python全套') Out[65]:
    In [66]: Course.objects.create(name='english') Out[66]:
    In [67]: c1,c2,c3 = Course.objects.all() In [68]: c1 Out[68]:
    In [69]: c2 Out[69]:
    In [70]: c3 Out[70]:
    In [71]: Student.objects.all().count() Out[71]: 3 In [72]: s1,s2,s3 = Student.objects.all() In [73]: s1 Out[73]:
    In [74]: s2 Out[74]:
    In [75]: s3 Out[75]:
    In [76]: e = Enroll() In [77]: e.course = c1 In [78]: e.student = s1 In [79]: e.save() In [80]: Enroll.objects.create(student=s1,course=c3) Out[80]:
    In [81]: Enroll.objects.create(student=s3,course=c1) Out[81]:
    In [82]: Enroll.objects.create(student=s1,course=c1) Out[82]:
    In [83]: c1.students Out[83]:
    .ManyRelatedManager at 0x7fdc1d9d46a0> In [84]: c1.students.all() Out[84]:
    ,
    ,
    ]> In [85]: s1.course_set.all() Out[85]:
    ,
    ,
    ]>

    多对多时如果指定了中间表(本例中是Enroll表),则不能用add,remove,set,必须用中间表

    OneToOne

  • 正向

    In [1]: from students.models import Student,StudentDetail,Course,Enroll,Grade                                                            In [3]: s1 = Student.objects.first()                                                                                                     In [4]: s2 = Student.objects.filter(name='na')                                                                                           In [5]: s3 = Student.objects.last()                                                                                                      In [6]: s1                                                                                                                               Out[6]: 
    In [7]: s2 Out[7]:
    ]> In [8]: s3 Out[8]:
    In [9]: sd = StudentDetail.objects.create(num='121204040',college='辽工',student=s1) In [10]: sd Out[10]:
    In [11]: sd.student Out[11]:
  • 反向

    In [12]: s1.studentdetail           #用模块名的小写,是个对象,不是管理器(没有_set)                                                                                                    Out[12]: 
    In [13]: s1.studentdetail.college Out[13]: '辽工'

    跨表查询

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

    #查询男生报了什么课程#最终是要查课程,所以用Course模型,通过本模型里的字段正向查  In [14]: res = Course.objects.filter(students__gender=1) #正向,本模型里的字段名+__想要查的字段                                                                                In [15]: print(res.query)                                                                                                                SELECT `students_course`.`id`, `students_course`.`name` FROM `students_course` INNER JOIN `students_enroll` ON (`students_course`.`id` = `students_enroll`.`course_id`) INNER JOIN `students_student` ON (`students_enroll`.`student_id` = `students_student`.`id`) WHERE `students_student`.`gender` = 1  In [16]: res                                                                                                                             Out[16]: 
    ,
    ,
    ,
    ]> In [17]: res = Course.objects.filter(students__name='long') In [18]: res Out[18]:
    ]> #查询报Python的学生#最终是要查学生,所以用Student模型,通过course反向查 In [19]: res = Student.objects.filter(course__name__contains='python') #相关模型名的小写+__相关字段名 In [20]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`gender`, `students_student`.`grade_id`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time` FROM `students_student` INNER JOIN `students_enroll` ON (`students_student`.`id` = `students_enroll`.`student_id`) INNER JOIN `students_course` ON (`students_enroll`.`course_id` = `students_course`.`id`) WHERE `students_course`.`name` LIKE BINARY %python% In [21]: res Out[21]:
    ,
    ,
    ]> #查询报了英语33期的学生 In [31]: res = Student.objects.filter(course__name__contains='english',grade__num__contains='33期') In [32]: res Out[32]:
    #查询缴费金额小于3000的学生 In [33]: res = Student.objects.filter(enroll__pay__lt=3000) In [34]: print(res.query) SELECT `students_student`.`id`, `students_student`.`name`, `students_student`.`age`, `students_student`.`gender`, `students_student`.`grade_id`, `students_student`.`qq`, `students_student`.`phone`, `students_student`.`c_time` FROM `students_student` INNER JOIN `students_enroll` ON (`students_student`.`id` = `students_enroll`.`student_id`) WHERE `students_enroll`.`pay` < 3000.0 #查询报了python课程的学生的班级有哪些 In [35]: res = Grade.objects.filter(student__course__name__contains='python') In [36]: print(res.query) SELECT `students_grade`.`id`, `students_grade`.`num`, `students_grade`.`name` FROM `students_grade` INNER JOIN `students_student` ON (`students_grade`.`id` = `students_student`.`grade_id`) INNER JOIN `students_enroll` ON (`students_student`.`id` = `students_enroll`.`student_id`) INNER JOIN `students_course` ON (`students_enroll`.`course_id` = `students_course`.`id`) WHERE `students_course`.`name` LIKE BINARY %python%

转载于:https://www.cnblogs.com/xiaogeldx/p/10479252.html

你可能感兴趣的文章
利用MySQL统计一列中不同值的数量方法示例
查看>>
微服务设计方法
查看>>
大项目之网上书城(九)——订单Demo
查看>>
Hexo主题实现多级分类显示
查看>>
UITableView-数据刷新
查看>>
(摘要)100个伟大的商业理念:理念16:深入投入,绘制蓝本
查看>>
Fiddler抓包配置具体步骤
查看>>
购物车程序
查看>>
Ubuntu18.0.4查看显示器型号
查看>>
C#实现 Eval
查看>>
渗透测试流程
查看>>
Windows 压缩文件到 Linux中解压文件名乱码
查看>>
Android的ListView详解
查看>>
Python开发基础--- Event对象、队列和多进程基础
查看>>
11.27号
查看>>
如何学习
查看>>
程序代码表现形式感悟
查看>>
java程序的框架
查看>>
HDU-4647 Another Graph Game 贪心,博弈
查看>>
easyui datagrid.gridFilter搜索插件
查看>>