Django模型系统三

Django模型系统三

一、关系表的数据操作

1、一对多

正向:如果一个模型有外键字段,通过这个模型对外键进行操作叫做正向。

#  更新:

   第一种,通过赋值的方式

    In [7]: from teacher.models import Student,Grade

    In [8]: g=Grade.objects.first()

    In [10]: s = Student.objects.first()  

    In [13]: s.grade=g

    In [14]: s.save()

   第二种,通过主键的方式

    In [15]: s2=Student.objects.last()

    In [16]: s2.grade_id=g.id

    In [17]: s2.save()

  总结:Foreginkey 字段的更新,跟普通字段没什么区别(比如换班级,如下:)

    In [18]: k = Grade.objects.create(name='python基础班',num='6')

    In [19]: s2.grade=k

    In [20]: s2.save()

  如果要把筛选出的几条学生数据,也把班级ID赋值于它的话,要用get取出班级的对象

    s = Student.objects.filter()[3:5]   

    g1 = Grade.objects.get(num='7')

     for i  in  s:
       i.grade=g1
       i.save()

  如果要更新一条数据,也要用get取出学生的对象

      s=Student.objects.get(name='刘玉凤') 

      g = Grade.objects.get(num='8')  

      s.grade=g     

      s.save()    

 通过Student表中grade外键字段,去查询Grade表中信息

    In [28]: res = Student.objects.filter(grade__name='django框架') 

    In [30]: print(res.query)
  SELECT `teacher_student`.`id`, `teacher_student`.`name`, `teacher_student`.`age`, `teacher_student`.`sex`, `teacher_student`.`QQ`, `teacher_student`.`phone`, `teacher_student`.`c_time`, `teacher_student`.`e_time`, `teacher_student`.`grade_id` FROM `teacher_student` INNER JOIN `teacher_grade` ON (`teacher_student`.`grade_id` = `teacher_grade`.`id`) WHERE `teacher_grade`.`name` = django框架

 #  删除:

  定义:只有外键设置了null=True,你就可以通过赋值None来删除关系

  In [31]: g2 = Student.objects.get(name='老徐')

  In [32]: g2.grade=None

  In [33]: g2.save()

 #  查询:

  通过Student表中grade外键字段(去过滤 ForeignKey 外键字段)去查询Student表中信息

    In [34]: g3 = Student.objects.filter(grade_ _num='7')

    In [35]: g3
    Out[35]: <QuerySet [<Student: 沈毅>, <Student: 顾晓峰>]>

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 反向:如果一个模型被另外一个模型外键关联,通过这个模型对关联它的模型进行操作叫做反向。

 #  查询:

 定义:通过管理器,默认管理器是有外键名称的小写加上_ _set(foo__set,foo是模型名称小写)

   如果在外键字段中加了related_name='students',那么后面的查询就以students类名来查询

   grade = models.ForeignKey('Grade',on_delete=models.SET_NULL, null=True,related_name='students')

   g.students.filter(name='老徐')    等同于   g.Student.objects.filter(name='老徐')

 #  增加:

add方法可增加多条记录,直接操作数据库

 例 :增加一条记录  g=Grade.objects.get(num='8')

          s=Student.objects.get(name='老徐')  

          g.students.add(s)  

 

   增加多条记录   s1=Student.objects.get(pk=6)   备注:pk=6表示第6条学生表数据

          s2=Student.objects.get(pk=7) 

          g = Grade.object.get(num='6') 

           g.students.add(s1,s2) 

  #  删除:

(删除只是删关系)通过 remove、clear 方法,直接操作数据库

   g = Grade.objects.get(num='6')  

  res = Student.objects.get(name='老徐')  

  g.students.remove(res)  

 #  改:

通过 set方法

   g = Grade.objects.get(num='8')  

     s1=Student.objects.get(pk=6) 

   s2=Student.objects.get(pk=7) 

    g.students.set([s1,s2])  

2、多对多

 定义:如果因为有额外字段,自定义了中间模型,我们需要通过中间模型的管理器,进行manytomany关系的创建和删除。

   默认情况,跟一对多中的(add,create,remove,clear)用法一致。

   唯一的区别是,多对多正向的时候,多对多字段就是个管理器。反向的时候,跟一对多的方向一至

    c2 = Course.objects.create(name='python全栈') 

    s2 = Student.objects.get(age='24') 

    In [19]: f=Enroll()

    In [20]: f.student=s2

    In [21]: c2=Course.objects.get(name='python全套')

    In [22]: f.course=c2

    In [23]: f.paid=9288

    In [24]: f.save()

3、一对一

  非常类似一对一字段,增、删、改、查和普通字段没有什么区别。

  反向的时候,使用模型的小写,也可以给related_name覆盖,这个就不是管理器,就是一个普通属性。

  注意:一个被一对一管理的模型,它的实例,如果没有被分配关系。  

    In [32]: from teacher.models import StudentDetail

    In [33]: dd = StudentDetail()

    In [34]: s = Student.objects.get(name='沈毅')

    In [35]: dd.student=s

    In [36]: dd.save()

    In [38]: s.studentdetail
    Out[38]: <StudentDetail: StudentDetail object (1)>

    In [39]: s.studentdetail.college
    Out[39]: '无学校'

    In [54]: s.studentdetail.college='北京大学'

    In [55]: dd.save()

 4、跨表查询

定义:要跨越关系,只需要使用跨越模型的相关字段的字段名,以下划线分隔,直到达到你想要的字段为止。

例:男生都报名了什么课程

  In [23]: res = Course.objects.filter(students__sex=1)

  In [24]: res 

  Out[24]: <QuerySet [<Course: python全栈>]>


去重可以这样写

  In [27]: res = Course.objects.filter(students__sex=2)

  In [28]: res
  Out[28]: <QuerySet [<Course: python全栈>, <Course: python全栈>, <Course: python全套>]>

  In [29]: res = Course.objects.filter(students__sex=2).distinct()

  In [30]: res
  Out[30]: <QuerySet [<Course: python全栈>, <Course: python全套>]>

例 :查询所有报了python课程的学员

  In [32]: res = Student.objects.filter(course__name__contains='python')   

例:查询所有报名了python全栈,在django框架班,第7期的学员

  In [36]: res = Student.objects.filter(course__name='python全栈',grade__name='django框架',grade__num='7') 

    注:grade_ _name表示Grade表里的name字段;course__name表示Course表里的name

例:学员报名了python课程的班级有哪些

  In [41]: res = Grade.objects.filter(students__course__name__contains='python').distinct()

  In [42]: res
  Out[42]: <QuerySet [<Grade: django框架>, <Grade: python基础班>]>

注:students是在Student里设置了  grade = models.ForeignKey('Grade',on_delete=models.SET_NULL, null=True,related_name='students')

 

posted on 2019-04-04 09:58  nickshen  阅读(163)  评论(0编辑  收藏  举报

导航