Django模型
知识点:
- 表关联对象
- 多表查询
表关联对象
前向查询
如果一个模型具有ForeignKey,那么该模型的实例将可以通过属性访问关联的(外部)对象。
>>> s1 = Student.objects.get(s_id=1)
>>> s1
<Student: Student<s_id=1,s_name=xiaoming>>
>>> s1.department
<Department: Department<d_id=6,d_name=CC>>
>>>
你可以通过外键属性获取和设置。和你预期的一样,对外键的修改不会保存到数据库中直至你调用save()。例如:
>>> s1.department
<Department: Department<d_id=6,d_name=CC>>
>>> dx = Department.objects.get(d_id=3)
>>> dx
<Department: Department<d_id=3,d_name=设计>>
>>> s1.department = dx
>>> s1.department
<Department: Department<d_id=3,d_name=设计>>
>>> s1.save()
反向查询
如果模型I有一个ForeignKey,那么该ForeignKey 所指的模型II实例可以通过一个管理器回前面有ForeignKey的模型I的所有实例。默认情况下,这个管理器的名字为foo_set,其中foo 是源模型的小写名称。
>>> d1 = Department.objects.get(d_id=1)
>>> d1
<Department: Department<d_id=1,d_name=软件>>
>>> d1.student_set.all()
<QuerySet [<Student: Student<s_id=2,s_name=xiaohong>>, <Student: Student<s_id=3,s_name=xiaohua>>, <Student: Student<s_id=4,s_name=xiaoxin>>, <Student: Student<s_id=5,s_name=小明>>]>
>>>
你可以在ForeignKey 定义时设置related_name 参数来覆盖foo_set 的名称。例如,如果Student模型改成department =models.ForeignKey('Department',related_name='student'),那么上面的示例代码应该改成这样:
>>> from blog.models import Student,Department,Course
>>> d1 = Department.objects.get(d_id=1)
>>> d1.student.all()
<QuerySet [<Student: Student<s_id=2,s_name=xiaohong>>, <Student: Student<s_id=3,s_name=xiaohua>>, <Student: Student<s_id=4,s_name=xiaoxin>>, <Student: Student<s_id=5,s_name=小明>>]>
>>>
处理关联对象的其它方法
add(obj1, obj2, ...)
添加一指定的模型对象到关联的对象集中。(一对多,多对多)
>>> d1 = Department.objects.get(d_id=4)
>>> d1
<Department: Department<d_id=4,d_name=AA>>
>>> st = Student.objects.get(s_id=6)
>>> st
<Student: Student<s_id=6,s_name=xx>>
>>> d1.student.add(st)
>>> c1 = Course.objects.get(c_id=2)
>>> st.course.add(c1)
create(**kwargs)
创建一个新的对象,将它保存并放在关联的对象集中。返回新创建的对象。(一对多,多对多)
>>> st
<Student: Student<s_id=6,s_name=xx>>
>>> st.course.create(c_name='c++')
<Course: Course<c_id=3,c_name=c++>>
>>> st.course.all()
<QuerySet [<Course: Course<c_id=3,c_name=c++>>]>
remove(obj1, obj2, ...)
从关联的对象集中删除指定的模型对象。(多对多)
>>> s3
<Student: Student<s_id=3,s_name=xiaohua>>
>>> c1
<Course: Course<c_id=2,c_name=java>>
>>> s3.course.all()
<QuerySet [<Course: Course<c_id=1,c_name=python>>, <Course: Course<c_id=2,c_name=java>>, <Course: Course<c_id=3,c_name=c++>>]>
>>> s3.course.remove(c1)
clear()
从关联的对象集中删除所有的对象。(多对多)
>>> s3.course.clear()
注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。
直接赋值
>>> s2
<Student: Student<s_id=2,s_name=xiaohong>>
>>> cs
<QuerySet [<Course: Course<c_id=3,c_name=c++>>]>
>>> s2.course.all()
<QuerySet []>
>>> s2.course = cs
>>> s2.course.all()
<QuerySet [<Course: Course<c_id=3,c_name=c++>>]>
多表查询
跨关联关系的查询
Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段:
# 查询学院名字为‘软件的’的学生的信息
Student.objects.filter(department__d_name='软件')
这种跨越可以是任意的深度。
它还可以反向工作。若要引用一个“反向”的关系,只需要使用该模型的小写的名称。
#查询学生名字中包含‘xiao’的学生的学院信息
Department.objects.filter(student__s_name__contains='xiao')
当你基于ManyToManyField或反向的ForeignKey来过滤一个对象时,有两种不同种类的过滤器。考虑Department/Student 关联关系 (一对多的关系)。
# 查询学号为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')
网友评论