• django模型基础(三)


    本文转载自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]: <QuerySet [<Grade: 33期-django框架>, <Grade: 256期-爬虫>]>
        In [4]: s = Student()                                                                                                           
        In [5]: s.name = 'xiaoge'                                                                                                              
        In [6]: g1 = Grade.objects.first()                                                                                                          
        In [7]: g1                                                                                                                             
        Out[7]: <Grade: 33期-django框架>
        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]: <Grade: 256期-爬虫>
        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]: <Student: na-0>	
        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]: <Student: long-0>
        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]: <QuerySet [<Student: xiaoge-0>, <Student: long-0>]>
        In [52]: g3.student_set.filter(name='xiaoge')     #查                                                                                     
        Out[52]: <QuerySet [<Student: xiaoge-0>]>
        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]: <QuerySet [<Student: long-0>]>
        In [56]: g3.student_set.clear()     #删2 清空                                                                                                   
        In [57]: g3.student_set.all()                                                                                                          
        Out[57]: <QuerySet []>
        In [58]: g3.student_set.set([s,s2])     #改	#set方法会先调用clear,再添加   (如果没有clear方法,clear不执行,直接添加)                                                                                         
        In [59]: g3.student_set.all()                                                                                                          
        Out[59]: <QuerySet [<Student: xiaoge-0>, <Student: na-0>]>
        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]: <QuerySet []>
      

    ManyToMany

    	In [64]: Course.objects.create(name='python全栈')                                                                                      
    	Out[64]: <Course: python全栈>
    	In [65]: Course.objects.create(name='python全套')                                                                                      
    	Out[65]: <Course: python全套>
    	In [66]: Course.objects.create(name='english')                                                                                         
    	Out[66]: <Course: english>
    	In [67]: c1,c2,c3 = Course.objects.all()                                                                                               
    	In [68]: c1                                                                                                                            
    	Out[68]: <Course: python全栈>
    	In [69]: c2                                                                                                                            
    	Out[69]: <Course: python全套>
    	In [70]: c3                                                                                                                            
    	Out[70]: <Course: english>
    	In [71]: Student.objects.all().count()                                                                                                 
    	Out[71]: 3
    	In [72]: s1,s2,s3 = Student.objects.all()                                                                                              
    	In [73]: s1                                                                                                                            
    	Out[73]: <Student: xiaoge-0>
    	In [74]: s2                                                                                                                            
    	Out[74]: <Student: na-0>
    	In [75]: s3                                                                                                                            
    	Out[75]: <Student: long-0>
    	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]: <Enroll: Enroll object (2)>
    	In [81]: Enroll.objects.create(student=s3,course=c1)                                                                                   
    	Out[81]: <Enroll: Enroll object (3)>
    	In [82]: Enroll.objects.create(student=s1,course=c1)                                                                                   
    	Out[82]: <Enroll: Enroll object (4)>
    	In [83]: c1.students                                                                                                                  
    	Out[83]: <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager at 0x7fdc1d9d46a0>
    	In [84]: c1.students.all()                                                                                                             
    	Out[84]: <QuerySet [<Student: xiaoge-0>, <Student: xiaoge-0>, <Student: long-0>]>
    	In [85]: s1.course_set.all()                                                                                                           
    	Out[85]: <QuerySet [<Course: python全栈>, <Course: english>, <Course: python全栈>]>
    

    多对多时如果指定了中间表(本例中是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]: <Student: xiaoge-0>
        In [7]: s2                                                                                                                             
        Out[7]: <QuerySet [<Student: na-0>]>
        In [8]: s3                                                                                                                             
        Out[8]: <Student: long-0>
        In [9]: sd = StudentDetail.objects.create(num='121204040',college='辽工',student=s1)                                                   
        In [10]: sd                                                                                                                            
        Out[10]: <StudentDetail: StudentDetail object (1)>
        In [11]: sd.student                                                                                                                    
        Out[11]: <Student: xiaoge-0>
      
    • 反向

        In [12]: s1.studentdetail       	#用模块名的小写,是个对象,不是管理器(没有_set)                                                                                                  
        Out[12]: <StudentDetail: StudentDetail object (1)>
        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]: <QuerySet [<Course: python全栈>, <Course: python全栈>, <Course: python全栈>, <Course: english>]>
        In [17]: res = Course.objects.filter(students__name='long')                                                                            
        In [18]: res                                                                                                                           
        Out[18]: <QuerySet [<Course: python全栈>]>
        #查询报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]: <QuerySet [<Student: xiaoge-0>, <Student: xiaoge-0>, <Student: long-0>]>
        #查询报了英语33期的学生
        		In [31]: res = Student.objects.filter(course__name__contains='english',grade__num__contains='33期')                                    
        In [32]: res                                                                                                                           
        Out[32]: <QuerySet []>
        #查询缴费金额小于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%
  • 相关阅读:
    序列化
    python_模块与包
    python_常用内置模块
    python_生成器
    python_文件操作
    你好,mysql
    2017年12月20日 内置对象
    2017年12月17日 ASP.NET 12个表单元素&&简单控件/复合控件
    2017年12月16日 ASP.NET基本用法
    2017年12月14日 LinQ高级查&&Asp.net WebForm Asp.net MVC
  • 原文地址:https://www.cnblogs.com/xiaogeldx/p/10479252.html
Copyright © 2020-2023  润新知