1.自定义主键字段的创建 AutoFiled(pirmary_key=True) # 一般不会自定义,int类型,自增长 一般不自定义主键.
2.order_by asc desc
from django.db.models.function import Lower
res = Student.objects.order_by(Lower('name').desc())
表关系的创建
OneToOne student = models.OneToOneField('Student', on_delete=models.CASCADE) #一般情况下关联表名用字符串,防止无法读取Student这个类.
OneToMany grade = models.ForeignKey('Grade', on_delete=models.SET_NULL, null=True)
ManyToMany
-
class Cousrse(models.Model):
name = models.CharField('课程名称',max_length=20)
students = models.ManyToMany('Student') 自动创建第三张表.
关联表的数据操作
OneToMany
正向 :一个模型如果定义了一个外键字段,通过这个模型操作外键 增删改查
反向 增删改查
-Many-to-Many 指定了中间表,add,remove,set 都不能用,必须用中间表 -One-to-One
跨表查询
1.实现课堂上的5个关联表的关系 2.练习课堂上的案例
关系表中的数据操作:
进入项目目录的IDLE:
为了能方便学习,我们进入项目的idle中去执行我们的操作,
通过python manage.py shell 就能进入当前目录下的IDLE
1.进入IDLE
2.查看当前的目录路径
3.导入我们项目中的模型类
关系表的数据操作:
1.先往数据表department中添加数据.
2.查看数据表student的表结构.
department_id字段就是外键关联的department表中的d_id字段
一对多表关系数据的添加:
3.往数据表student中添加数据的第一种方式
s = Students()
In [6]: s.name = '石麒详'
In [7]: g1 = Grade.objects.first()
In [8]: g1 Out[8]: <Grade: Grade object (1)>
In [10]: s.grade = g1
In [11]: s.grade Out[11]: <Grade: Grade object (1)>
In [13]: s.save()
In [14]: s.grade Out[14]: <Grade: Grade object (1)>
4.往数据表student中添加数据的第二种方式
s1 = Student(name='二')
g2 = Grade.objects.last()
se.grade_id = g2.id
s2.save
这两种方式的效果是一样的.
1.第一种方式就是跟之前的一样,用传参的方法添加,需要注意的是外键的值必须是关联表中已经存在的值.
2.第二种方式是用的属性赋值的方式,因为我们在模型类有定义了一个department的属性,而这个属性的对象的类型必须是department表的类实例对象
删除:s2.grade = None
s2.save()
查:
s2.grade.name
s2.grade.num
表关联对象的访问:
Student的模型类中我们有定义department的属性,所以当我们去访问的时候,可以直接通过student.department的形式去找到某个学生的所属学院是哪个.
那么如果我们也希望在在访问某个学院的实现对象的学生的时候改怎么访问呢???
如果模型I有一个ForeignKey,那么该ForeignKey 所指的模型II实例可以通过一个管理器回前面有ForeignKey的模型I的所有实例。默认情况下,这个管理器的名字为foo_set,其中foo 是源模型的小写名称。
例子:g3.students_set <django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager at 0x7f097b7a0b70>
g3.students_set.create(name='王五') 反向增加.
g3.students_set.add(s) #直接加入一个s对象
create,add,立刻马上操作数据库,add可以加多个
可以在定义时设置related_name 参数来覆盖foo_set 的名称.
添加了related_name的参数后,重新打开一个IDLE,
访问时就能直接用设置的参数作为属性了.
处理关联对象的一些方法:
add(obj1, obj2, ...) 添加的已经存在数据库的数据
添加一指定的模型对象到关联的对象集中。
1.d1.student的管理器有add的方法.
2.例子中的s2能添加成功是因为设置了student表中department字段允许为空了.
create(\kwargs) 添加不存在的数据 ,将数据直接存入数据库
创建一个新的对象,将它保存并放在关联的对象集返回新创建的对象。
remove(obj1, obj2, ...)
从关联的对象集中删除指定的模型对象。
删除的是关系表中的数据
因为我们有修改student表中的department_id字段允许为空,所以当删除的时候这个字段值为NULL.删除字段必须设置null为True
clear() 从关联的对象集中删除所有的对象
remove,clear是立刻马上执行.
g3.student_set.set([s,s2])
set方法先调用clear,然后添加
注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。
多表查询----跨关联关系的查询:
Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动帮你处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段:
例子:Students.objectt.filter(grade__name='django框架') #此sql语句用内连接完成查询.
查询学院名字为‘计算机学院’的学生的信息
Student.objects.filter(department__d_name='计算机学院')
它还可以反向工作。若要引用一个“反向”的关系,只需要使用该模型的小写的名称。
查询学生名字中包含 '小' 的学生的学院信息
Department.objects.filter(students_namecontains='小')
查询学号为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')
ManyToMany
add,set,remove都是我们没有指定中间表时候使用.
只要是反向,就用模型的小写加--set.
ManyToManyField相当于一个管理器:
例子:c1.students.all()
通过ManyToManyField字段的介入,就可以不需要中间表进行查询.
OneToOne反向查询中不需要set,直接通过模型的小写调用一个对象,不是管理器.
例子:s1.studentdetail.college
查询性别为1的学生选择的课程
res = Course.objects.filter(students__sex=1)
查询选择python课程的学生:
Students.objects.filter(course--name--counatins='python')
查询选择了英语33期的学生
res = Students.objects.filter(course--name--contains='english',grade--num--contains='33')
查询报名学费小于3000的学生
Students.objects.filter(enroll--pay--lt=3000)
查询报名了python的学生所在的年级
Grade.objects.filter(student--course--name--contains='python')
在执行makemigrations的时候,django自动在数据库中创建一个django-migrations表,记录执行的迁移文件名,如果手动删除了迁移文件,再执行makemigrations时,生成的相同的迁移文件名不会执行.所以还要手动在django-migrations表中手动删除同名记录,才能执行migrate.但是数据库没有相应的回调,执行时会报错.
迁移回滚
python manage.py migrate teacher 0001 #最后是以前版本的迁移文件名
Students.objects.only('name') ,返回的是一个对象列表,可以索引取其他属性,提高效率.only查询id和name,再查询其他属性时又执行查询数据库.
Students.objects.values('name') ,返回的是一个QuerySet,只能索引取到name字典对象,不可以索引取其他属性
左连接查询的一个例子:
res = Students.object.values('name','grade--name') #左连接查询表的年级