模型model
django的ORM系统
ORM概念:对象关系映射(Object Relational Mapping,简称ORM)
ORM的优势:不用直接编写SQL代码,只需像操作对象一样从数据库操作数据。
- 模型类必须都写在app下的models.py文件中
- 模型如果需要映射到数据库,所在的app必须被安装
- 一个数据表对应一个模型类,表中的字段,对应模型中的类属性
配置数据库
1.在settingss.py里面配置DATABASSES
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', # 数据库引擎 'NAME': 'mydb', #数据库名称 'USER': 'admin', # 链接数据库的用户名 'PASSWORD': 'Root110qwe', # 链接数据库的密码 'HOST': '127.0.0.1', # mysql服务器的域名和ip地址 'PORT': '3306', # mysql的一个端口号,默认是3306 } }
2.设置连接器
需要安装pymysql,安装方法不再赘述
在主目录下创建 __init__.py 文件,写入如下两行代码
import pymysql pymysql.install_as_MySQLdb() #将pymysql作为连接器
一、模型数据表的创建
1.在对应的APP目录的 models.py定义模型类,即建表
#创建一个数据表 class Demo(models.Model): id = models.AutoField(primary_key=True) #设置为主键 name = models.CharField(max_length=30) #添加一个name的字段 age = models.IntegerField() #添加一个age的字段
2.映射数据库
法一
找到 Tools 下面的 Run manage.py Task
生成文件映射 makemigrations ,后跟APP名,如果不指定,则全部添加;
将映射提交到数据库 migrate
法二
在SSH里执行命令 python manage.py makemigration 和 python manage.py migrate
3.检查
可以看到,里面成功创建了 db_test_demo ( 数据库表名 = APP名_模型类名 )的数据表,其他的是django自带
看一下设计结构
二、数据的常规操作
以下数据的操作是使用视图函数,通过访问url来调用函数,视图函数和路由配置不再赘述,只展示视图函数的函数体部分
1.插入
法一
Chancey = Demo(name='Chancey',age=18) Chancey.save()
法二
Chancey = Demo() Chancey.name = 'Chancey' Chancey.age = 18 Chancey.save()
法三
Demo.objects.create(name='Chancey',age=18)
法四
Demo.objects.get_or_create(name='Chancey',age=18)
这时,在访问URL的时候报错
大致意思是,什么什么三个了,回到数据库看一下
发现也没有成功插入数据
这是因为该方法不会重复添加相同的数据,这里随便改一下
Demo.objects.get_or_create(name='Make',age=20)
成功添加
2.查询
查询之前需要添加一个 __str__ 的魔术方法,以格式化输出
def __str__(self): return 'Demo<id=%s,name=%s,age=%s>'%(self.id,self.name,self.age)
法一(get)
rs = Demo.objects.get(name='Make') print(rs)
这里返回的是一个实例对象,且get方法查找只能查找条件唯一的数据
法二(filter)
rs = Demo.objects.filter(name='Chancey') print(rs)
控制台可以看到 <QuerySet [<Demo: Demo<id=1,name=Chancey,age=18>>, <Demo: Demo<id=2,name=Chancey,age=18>>, <Demo: Demo<id=3,name=Chancey,age=18>>]> ,这是一个类似于集合的Query_Set对象,该对象可迭代、可被构造、可过滤、可切片、可被作为参数传递。
法三(all)
rs = Demo.objects.all() print(rs)
查询所有,不再赘述
3.更改
法一
rs = Demo.objects.get(name='Make') #获取类的属性 rs.name = 'Mary' #修改类的属性 rs.save() #记得保存
法二
Demo.objects.filter(name='Mary').update(name='Make') #最容易理解
法三
添加新的字段可以在定义模型类里面添加,这会改变表的结构
添加之后重新生成映射文件并且提交到数据库
4.删除
Demo.objects.filter(name='Chancey').delete()
三、常用的查询
常用的查询方法
- 获取所有记录 rs = Demo.objects.all()
- 获取第一条数据 rs = Demo.objects.first() last亦然,即最后一条数据
- 指定条件 rs = Demo.objects.filter(name='Make',age=20)
- 指定条件 rs = Demo.objects.get(name='Chancey') 和filter的区别就是get指定的条件只能是唯一的
- 排除条件 rs = Demo.objects.exclude(name='Chancey')
- 排序 rs = Demo.objects.order_by('age') #按照指定条件进行排序,反向前加'-'即可
- 将返回的对象转换成字典 rs = Demo.objects.all().values() 既然Sery_Set对象可跌,转换成字典意义不大
- 获取当前查询的总数量 rs = Demo.objects.count()
常用的查询条件
内容非常简单,不再详述其用法
四、常用字段及参数
常用的字段类型对应到mysql的关系
1. IntegerField : 整型,映射到数据库中的int类型。
2. CharField: 字符类型,映射到数据库中的varchar类型,通过max_length指定最大长度。
3. TextField: 文本类型,映射到数据库中的text类型。
4. BooleanField: 布尔类型,映射到数据库中的tinyint类型,在使用的时候,传递True/False进去。如果要可以为空,则用NullBooleanField。
5. DateField: 日期类型,没有时间。映射到数据库中是date类型, 在使用的时候,可以设置DateField.auto_now每次保存对象时,自动设置该字段为当前时间。设置DateField.auto_now_add当对象第一次被创建时自动设置当前时间。
6. DateTimeField: 日期时间类型。映射到数据库中的是datetime类型, 在使用的时候,传递datetime.datetime()进去。
常用的参数
primary_key: 指定是否为主键。
unique: 指定是否唯一。
null: 指定是否为空,默认为False。
blank: 等于True时form表单验证时可以为空,默认为False。
default: 设置默认值。
DateField.auto_now: 每次修改都会将当前时间更新进去,只有调用,QuerySet.update方法将不会调用。这个参数只是Date和DateTime以及TimModel.save()方法才会调用e类才有的。
DateField.auto_now_add: 第一次添加进去,都会将当前时间设置进去。以后修改,不会修改这个值
五、表关系
Django里面已经封装好了诸多方法,只需要调用即可
举个例子,现在需要实现如下表关系,对于mysql层面上的表关系不太理解的可以去数据库栏目里
可以点击下载附件
分析以上表关系,可以总结出
现在映射到模型
建表
实现一对多(即学院信息表和学生信息表)
#创建学院信息表 class Department(models.Model): d_id = models.AutoField(primary_key=True) d_name = models.CharField(max_length=30) def __str__(self): return 'Department<d_id=%s,d_name=%s>'%(self.d_id,self.d_name) #创建学生信息表 class Student(models.Model): s_id = models.AutoField(primary_key=True) s_name = models.CharField(max_length=30) department = models.ForeignKey('Department',on_delete=models.CASCADE) #这里的on_delete是级联删除 def __str__(self): return 'Student<s_id=%s,s_name=%s>'%(self.s_id,self.s_name)
之后还是原来的套路,即 makemigrations 和 migrate
可以看到,直接用 models.ForeignKey 即可完成外键关联
再来数据库里面看看
查看下表结构
实现一对一(创建学生详情表,和学生信息表一对一)
class Student_detail(models.Model): student = models.OneToOneField('Student',on_delete=models.CASCADE) #一对一的关系,主从不影响 gender = models.BooleanField(default=True) height = models.IntegerField() wight = models.IntegerField()
查看表结构
实现多对多(创建课程表,和学生信息表多对多)
class Course(models.Model): c_id = models.AutoField(primary_key=True) c_name = models.CharField(max_length=30) student = models.ManyToManyField('Student')
查看数据库
不难发现,这里多出来了 db_test_course 和 db_test_course_student
这里不用自行创建中间信息表,Django会自动创建中间信息表
看下两张表的结构
六、表关联对象的访问
一对多关系
先给 department 表插入数据(只写函数体部分,这种方法是通过视图函数来使用,所以必须分配路由并返回response对象)
Department.objects.create(d_name='信息工程') Department.objects.create(d_name='经济管理') Department.objects.create(d_name='纺织服装') Department.objects.create(d_name='艺术传媒') Department.objects.create(d_name='商务外语')
查询
d1 = Department.objects.get(d_id=1) s1 = Student.objects.get(s_id=1) print(s1.department.d_name) #正向查询,查该生的所属学院 print(d1.student_set.all()) #反向查询,用_set做管理器,查这个学院的学
可以在定义时设置related_name 参数来覆盖foo_set 的名称
- 1.d1.student的管理器有add的方法.
- 2.例子中的s2能添加成功是因为设置了student表中department字段允许为空了
一对一关系
std = Student_detail.objects.get(id=2) print(std.student.s_name) #正向查询,查这个学生的名字 print(s1.student_detail.age) #反向查询,查年龄
注意对于所有类型的关联字段,add()、create()、remove()和clear()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法
八、多表查询
print(Student.objects.filter(department_id=2)) #查询学院的所有学生 print(Student.objects.filter(course__c_id=1)) #查询选该课程的所有学生 print(Department.objects.filter(student__s_name__contains='何')) #查询名字里包含‘何字’的学生的学院 print(Course.objects.filter(student__s_id=1.all())) #查询学号为1的学生所选的课程 print(Student.objects.filter(course__c_id=1).all()) #查询课程1报名的同学 print(Department.objects.filter(student__course__c_id=1)) #查询报名了某课程的学生的学院
Django 提供一种强大而又直观的方式来“处理”查询中的关联关系,它在后台自动处理JOIN。 若要跨越关联关系,只需使用关联的模型字段的名称,并使用双下划线分隔,直至你想要的字段