django框架(4)

十三、ORM

概念:对象关系映射

本质:用面向对象的方式,去描述数据库,操作数据库,达到不用编写sql语句对数据库进行增删改查。

优势:不用直接编写SQL代码,只需像操作对象一样从数据库操作数据

类—》表

类属性—》字段

实例—》数据

所有的代码写在moudles里面

1.模型的创建与映射

1.模型文件:student/models.py
2.创建模型:
  • varchar—》models.CharField(max_length) 字符串 max_length设置长度

  • int—》SmallIntegerField(IntegerField)数字

  • models.DateTimeField(auto_now_add=True) 时间(自动填充当前时间)

  • models.DateField 日期

  • longtext—》models.TextField 文本

class Student(models.Model):
    name = models.CharField(max_length=20)
    age = models.SmallIntegerField()
    sex = models.SmallIntegerField(default=1)  #设置默认值
    qq = models.CharField(max_length=20)
    phone = models.CharField(max_length=20)
    # c_time = models.DateTimeField(verbose_name='数据创建时间',auto_now_add=True)#auto_now_add 自动填充当前时间
    c_time = models.DateTimeField('数据创建时间',auto_now_add=True)#名字必须放在第一位
3.激活模型
  • 1.检查app是否被注册(settintg里的installed_app)
  • 2.迁移

python manage.py makemigrations teacher#指定app迁移

python manage.py makemigrations #迁移全部模型

(djangoApp) pyvip@VIP:~$ workon djangoApp
(djangoApp) pyvip@VIP:~$ ls
config  djangoProject  install.sh  py_case  snap  summer-2  公共的  模板  视频  图片  文档  下载  音乐  桌面
(djangoApp) pyvip@VIP:~$ cd djangoProject/CRM
(djangoApp) pyvip@VIP:~/djangoProject/CRM$ python manage.py makemigrations

python manage.py qslmigrate student 0001 #查看原生sql语句

以上操作完成,保存更改,但是操作还没生效。

  • 迁移生效
python manage.py migrate
  • 重点:注意

    迁移功能非常强大,允许我们在开发项目是对模型随时更改,不需要删除数据库或者创建新的表----实时去升级数据库而不丢失数据。

4.总结,模型修改三部曲

1.修改模型(创建模型)

2.运行 python manage.py makemigrations 创建迁移

3.运行 python manage.py migrate 迁移生效

2.模型数据的增删改查

进入交互式python shell中

pip install ipython
python manage.py shell

1.增

from student.models import Student  #导入模型
#第一种方式,需要将创建的对象保存
s = Student(name='summer',age=20,qq='12345') 
s.save()

#第二种方式#创建空实力,在属性赋值,对象要保存
s1 = Student()
s1.name = 'july'
s1.age = 18

#第三种方式#create,不用保存
Student.objects.create(name='april',age = 19) 
#第四种方式#有就取值,没有就创建记录
s = Student.objects.get_or_create(name = 'blue') 

2.查

#查所有
In [15]: res = Student.objects.all()                                                          

In [16]: res                                                                                  
Out[16]: <QuerySet [<Student: Student object (1)>, <Student: Student object (2)>, <Student: Student object (3)>, <Student: Student object (4)>]>

In [18]: print(res.query)                                                                     
SELECT `student_student`.`id`, `student_student`.`name`, `student_student`.`age`, `student_student`.`sex`, `student_student`.`qq`, `student_student`.`phone`, `student_student`.`c_time` FROM `student_student`

#查单条,只能返回一个对象,同时符合条件的有多个会报错
Student.objects.get(pk=1)  #逐渐不一定会命名为id,

2 Student.objects.filter(age=18)  

3 res = Student.objects.filter(age=18)   print(res.query) 

3.改

 s = Student.objects.get(id = 4) 
 s                               <Student: blue>
 s.phone = '1254135'             
 s.save()
 
 
 
 第二种,一次修改多条数据
 Student.objects.filter(sex = 1).update(sex=0) 

4.删

s = Student.objects.get(pk = 3) 

s.delete()  

批量删除
Student.objects.filter(age=18).delete() 
Student.objects.all().delete() 

3.字段类型+属性

Field常用参数

primary_key: 指定是否为主键。
unique: 指定是否唯一。
null: 指定是否为空,默认为False。
blank: 等于True时form表单验证时可以为空,默认为False。
default: 设置默认值。
DateField.auto_now: 每次修改都会将当前时间更新进去,只有调用,QuerySet.update方法将不会调用。这个参数只是Date和DateTime以及TimModel.save()方法才会调用e类才有的。
DateField.auto_now_add: 第一次添加进去,都会将当前时间设置进去。以后修改,不会修改这个值

如果你在最起初的时候去设置primary_key和unique,必须在刚刚开始是就去加上,如果一定要在后面加上就要删除全部的数据库,并且在mysql里删除有关app的一切

4.查询方法

首先在环境下进入python编写页面

python manage.py shell
from teacher.modles import Student
#然后插入数据
#get all filter

#all
1.
In [7]: Student.objects.all()                             
Out[7]: <QuerySet [<Student: summer>, <Student: july>, <Student: april>, <Student: hah>]>


#filter
2.
In [10]: Student.objects.filter(name='summer')            
Out[10]: <QuerySet [<Student: summer>]>



3.
res = In [12]: res = Student.objects.filter(name='july')        

In [13]: print(res.query)                                 
SELECT `student_student`.`num`, `student_student`.`name`, `student_student`.`age`, `student_student`.`sex`, `student_student`.`qq`, `student_student`.`phone`, `student_student`.`c_time`, `student_student`.`x_time` FROM `student_student` WHERE `student_student`.`name` = july


#get
Student.objects.get(name='april')

共同点:

1.都是通过objects去实现——》objects:每一个django模型类,都有一个默认管理器,objects

其他
1.
In [15]: Student.objects.first() #查询第一条数据                         
Out[15]: <Student: summer>#返回一个对象

2.
In [16]: Student.objects.last() #查询最后一条数据                          
Out[16]: <Student: hah>#返回一个对象

3.
In [17]: Student.objects.exclude(name='summer')    #与filter用法相同,作用相反,排除       
Out[17]: <QuerySet [<Student: july>, <Student: april>, <Student: hah>]>

In [18]: Student.objects.filter(name='summer')            
Out[18]: <QuerySet [<Student: summer>]>


4.指定字段查询
In [19]: Student.objects.values('name')                   
Out[19]: <QuerySet [{'name': 'summer'}, {'name': 'july'}, {'name': 'april'}, {'name': 'hah'}]>#返回字典

In [23]: res = Student.objects.values('name')             
#他可以查指定字段的东西,但是其余的东西却不能找到
In [24]: res[2]['name']                                   
Out[24]: 'april'

#如果要拿全部的东西,需要用到only

In [27]: res = Student.objects.only('name')               

In [28]: res                                              
Out[28]: <QuerySet [<Student: summer>, <Student: july>, <Student: april>, <Student: hah>]>
In [30]: res[2]                                           
Out[30]: <Student: april>

In [31]: res[2].name                                      
Out[31]: 'april'

In [32]: res[2].sex                                       
Out[32]: 0


#和only相反的defer(排除)
#####排序
#order_by:根据指定字段排序
In [37]: res = Student.objects.order_by('age')            

In [38]: print(res.query)  
SELECT `student_student`.`num`, `student_student`.`name`, `student_student`.`age`, `student_student`.`sex`, `student_student`.`qq`, `student_student`.`phone`, `student_student`.`c_time`, `student_student`.`x_time` FROM `student_student` ORDER BY `student_student`.`age` ASC
ASC表示正序

In [40]: res = Student.objects.order_by('-age')            

In [41]: print(res.query)                                  
SELECT `student_student`.`num`, `student_student`.`name`, `student_student`.`age`, `student_student`.`sex`, `student_student`.`qq`, `student_student`.`phone`, `student_student`.`c_time`, `student_student`.`x_time` FROM `student_student` ORDER BY `student_student`.`age` DESC
DESC表示反序


##切片
In [43]: Student.objects.all()[:2]                         
Out[43]: <QuerySet [<Student: summer>, <Student: july>]>


##查询
#单条件
In [47]: Student.objects.filter(age=20,sex=0)              
Out[47]: <QuerySet [<Student: summer>, <Student: april>]>

#多条件查询,需要导入Q库
In [48]: from django.db.models import Q                    

In [49]: Student.objects.filter(Q(sex=0),Q(age=20)|Q(age=19
    ...: ))                                                
Out[49]: <QuerySet [<Student: summer>, <Student: april>]>

5.查询条件

#exatc 准确匹配
 WHERE `student_student`.`name` = summer


#iexatc 不区分大小写匹配
WHERE `student_student`.`name` LIKE summer

#contains 包含匹配
WHERE `student_student`.`name` LIKE BINARY %s%

#icontains 不匹配大小写的包含匹配
 WHERE `student_student`.`name` LIKE %s%
# in
In [63]: Student.objects.filter(pk__in=[1,2])              
Out[63]: <QuerySet [<Student: summer>, <Student: july>]>

In [65]: Student.objects.filter(sex__in='01')              
Out[65]: <QuerySet [<Student: summer>, <Student: july>, <Student: april>, <Student: hah>]>

#子查询
res = Student.objects.filter(name__icontains='s'). only('name') 
res1 = Student.objects.filter(pk__in=res).only('name')                  print(res1.query)                                 
SELECT `student_student`.`num`, `student_student`.`name` FROM `student_student` WHERE `student_student`.`num` IN (SELECT U0.`num` FROM `student_student` U0 WHERE U0.`name` LIKE %s%)

#gt大于 gte大于等于 lt小于 lte小于等于
In [71]: Student.objects.filter(pk__gt=2)                  
Out[71]: <QuerySet [<Student: april>, <Student: hah>]>

#range,范围查找
In [74]: Student.objects.filter(age__range=(0,21))         
Out[74]: <QuerySet [<Student: summer>, <Student: july>, <Student: april>, <Student: hah>]>

#聚合分组annotate
In [76]: from django.db.models import Count,Avg,Max,Sum    

In [77]: res = Student.objects.values('sex').annotate(ren=C
    ...: ount('sex'))                                      

In [78]: print(res.query)                                  
SELECT `student_student`.`sex`, COUNT(`student_student`.`sex`) AS `ren` FROM `student_student` GROUP BY `student_student`.`sex` ORDER BY NULL

6.表关系的实现

一对一,一对多,多对多

1.表关系

一个班级-----多个学生

问:foreignkey放在哪?

​ 一个班级找一个学生

​ 一个学生找一个班级

所以foreignkey放在学生表

from django.db import models

# Create your models here.
class Teacher(models.Model):
    name = models.CharField('学生姓名',max_length=20)
    age = models.SmallIntegerField('年龄',null=True)
    sex = models.SmallIntegerField('性别',null=True)
    qq = models.CharField('QQ',max_length=20,unique=True)
    phone = models.CharField('电话',max_length=20,unique=True)
    c_time = models.DateTimeField('创建时间',auto_now_add=True)
    # detail = models.OneToOneField('TeacherDetail',on_delete=models.SET_NULL,null=True)
    grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True)

    def __str__(self):
        return"{}-{}".format(self.name,self.age)



class TeacherDetail(models.Model):
    college = models.CharField('学院',max_length=20)
    teacher = models.OneToOneField('Teacher',on_delete=models.CASCADE)


class Grade(models.Model):
    name = models.CharField("班级名称",max_length=20)
    num = models.CharField('班期',max_length=20)


class Coures(models.Model):
    name = models.CharField("课程名称",max_length=20)
    teachers = models.ManyToManyField('Teacher')
2.回滚
python manage.py migrate teacher 0001
注意回滚后必须把最后一次记录删了
3.中间表自己创建
前面需要在一个表上加上through:
class Coures(models.Model):
    name = models.CharField("课程名称",max_length=20)
    teachers = models.ManyToManyField('Teacher',through='Enroll')#在关联的表上面添加through,这样可以不按照他给你的teacher_coures创建中间表,而是按照自己的表格来创建

#中间表
class Enroll(models.Model):
    teacher = models.ForeignKey('Teacher',on_delete=models.CASCADE)
    course = models.ForeignKey('Coures',on_delete=models.CASCADE)
    pay = models.FloatField('缴费金额',default=0)
    c_time = models.DateTimeField('报名时间',auto_now_add=True)

4.OneToMany(正向/反向增删改查)

正向:一个模型有外键字段,通过这个模型对外键进行操作就叫正向
反向:一个模型如果被另一个模型外键关联,通过这个模型对关联他的模型进行操作
class Student(models.Model):
	....
	grade = models.ForeignKey('Grade',on_delete=models.SET_NULL,null=True)
#增:通过属性赋值
In [12]: s1 = Teacher(name='summer',age=20,sex=1,qq='123',
    ...: phone='456',grade = g1)                          
In [13]: s1.save() 
#增:主键方式
s3 = Teacher(name='april',age=18,sex=0,qq='1357',phone='2468')  
s3.grade_id = g3.id               s3.save()  

#查
In [22]: s1                                                    
Out[22]: <Teacher: summer-20>

In [23]: s2.grade.name                                         
Out[23]: '爬虫班'

In [25]: Teacher.objects.filter(grade__name='django框架') 

Out[25]: <QuerySet [<Teacher: summer-20>]>

#删:删除两个之间的关联关系
In [26]: s1.grade = None                                       
In [27]: s1.save()                                             
In [28]: s1.grade  

反向的管理器:如果一个模型(Teacher)有一个ForeignKey(grade),那么这一个外建模型的实例为g1将可以返回一个teacher模型的所有市里的管理器(teacher_set)(teacher是模型名,小写)

#增
#1.通过teacher_set管理器
new_s = g2.teacher_set.create(name='fat',age=20,sex=1,qq='12367',phone='12537')  
#2.一次多个数据
In [32]: s1,s2,s3 = Teacher.objects.filter(id__lte=3);         

In [33]: g1.teacher_set.add(s1,s2,s3) 

#改
g2.teacher_set.set([s2,s3])  

#删
g2.teacher_set.remove(s2,s3) 

g2.teacher_set.clear() 

#查:和objects一样使用
g1.teacher_set.all() 

In [44]: g1.teacher_set.filter(age=18)                         
Out[44]: <QuerySet []>

5.ManyToMany

class Course(models.Model):
	...
	teachers = models.ManyToManyField('Tracher',through='Enroll')
反向模型管理器:Course_set
替换模型名:related_name--可以通过这个来指定属性替代course_set
teachers = models.ManyToManyField('Teacher',through='Enroll',related_name = 'course')

因为改了数据,因此需要重新迁移数据。

python manage.py makemigrations
python manage,py migrate
#再次导入ipython
python manage.py shell
就可以再次进行编写
In [1]: from teacher.models import Teacher,TeacherDetail,Coures,Enroll,Grade  
#增
c1 = Course.objects.create(name='python')  
s1 = Teacher.objects.first() 
#关联
In [7]: e = Enroll()             
In [8]: e.course = c1             
In [9]: e.teacher = s1 
In [14]: e.save() 

#查
#正向查找
In [21]: c1.teachers.all()       
Out[21]: <QuerySet [<Teacher: summer-20>]>
#反向查找
In [19]: s1.course.all()         
Out[19]: <QuerySet [<Course: Course object (1)>]>

6.OneToOne

正向:foreignkey在哪个字段下面就是通过这个字段去找关联的东西。

正向:一对一字段所载的模型,通过这个模型去访问关联的模型
In [23]: d1 = TeacherDetail(college='宁夏理工学院')                  
In [24]: d1.teacher = s1         
In [25]: d1.save()
#查
In [26]: TeacherDetail.objects.values('college','teacher__name','teacher__qq')               
Out[26]: <QuerySet [{'college': '宁夏理工学院', 'teacher__name': 'sum'teacher__qq': '123'}]>
反向:前面的反向都是通过管理器,泽丽反向类似正向
In [28]: s = Teacher(name='yl',age=19,sex=0,qq='151551',phone='357337')    #原始模型的小写名  
In [29]: s.studentdetail = d1     
In [30]: s.save()  
#查
Teacher.objects.values('name','qq','teacherdetail__college')

7.跨表查询

#如果我想要跨越关系,只需要使用跨模型的向相关字段的字段名以双下划线隔开,知道达到想要的结果为止。
#男老师的课程
In [56]: Course.objects.filter(teachers__sex=1)          
Out[56]: <QuerySet [<Course: Course object (1)>]>
#报名python课程的老师
Teacher.objects.filter(course__name='python') 
####contions模糊查询
#及报名python也是django11期学员
Teacher.objects.filter(course__name='python',grade__num__contains='11') 

#查缴费小于3000的老师
In [71]: e = Enroll()  
In [72]: e.course = c2 
In [73]: e.teacher = s5 
In [74]: e.pay = 1000 
In [75]: e.save()  
In [68]: Teacher.objects.filter(enroll__pay__lt=3000)       
Out[68]: <QuerySet [<Teacher: summer-20>, <Teacher: july-19>, <Teacher: april-18>, <Teacher: fat-20>]>
#查询学员报名课程的班级有哪些
In [5]: Grade.objects.filter(teacher__course__name='python') 
Out[5]: <QuerySet [<Grade: django框架>, <Grade: django框架>, <Grade: 基础班>]>
#去重
In [6]: Grade.objects.filter(teacher__course__name='python').distinct()   
Out[6]: <QuerySet [<Grade: django框架>, <Grade: 基础班>]>

如果想获取更多有关python的信息,和想玩python制作的小程序,可以关注微信公众号(dreamspy)。我们一起用python改变世界,一起用python创造梦想。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值