标签:avos mysq ever ref fun 外键约束 blog comment com
ORM即Object Relational Mapping(对象关系映射)
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的—“虚拟对象数据库”。
在Django中具体的对应方式为:
Django默认使用的是sqlite,如果想使用mysql来存储数据,需要改变成相应的数据库引擎,具体如下:
将
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.sqlite3‘,
‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
}
}
改成
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.mysql‘,
‘NAME‘:‘mysite‘,
‘USER‘: ‘root‘,
‘PASSWORD‘: ‘000000‘,
‘HOST‘: ‘127.0.0.1‘,
‘PORT‘: ‘3306‘,
}
}
在init.py文件中加上
import pymysql pymysql.install_as_MySQLdb()
数据库表的创建在ORM中就是类的创建。
class student(models.Model):
name=models.CharField(max_length=20)
num=models.IntegerField()
school=models.ForeignKey(school,on_delete=models.CASCADE)
teacher=models.ManyToManyField(teacher)
def __str__(self):
return self.name
class school(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
class teacher(models.Model):
name = models.CharField(max_length=20)
def __str__(self):
return self.name
首先在models.py中简单的创建了三个表,然后需要在当前项目有manage.py文件目录下的cmd或者pycharm中的terminal下执行如下命令来同步数据库:
python manage.py makemigrations #为模型改变生成迁移文件
python manage.py migrate #应用数据库迁移
这时在数据库中就会显示有这3张表了
几个常用的类型:
几个常用的参数:
具体参考Django官方文档https://docs.djangoproject.com/en/2.1/ref/models/fields/
即一对多的关系
school=models.ForeignKey(school,on_delete=models.CASCADE)
在建表时为school添加外键约束,在数据库中的显示为
这里的id是自动创建的,school_id是school添加外键产生的
一对一的创建即在外键创建好后给school_id添加UNIQUE=True的属性
teacher=models.ManyToManyField(teacher)
这样Django会默认添加一张表为
表示多对多的关系。
除了这种方式也可以手动创建一个表,手动添加两个外键来实现多对多。
增删改查的操作会在视图函数中进行,所以要先引入到views.py中
from blog.models import *
create方式
student.objects.create(name="student1",num=1,school=school_obj)
或者
student.objects.create(**{"name":"student1","num"="1","school"=obj"})
save方式
student_obj=student(
name="student1",num=1,school=school_obj
)
student_obk.save()
或者
student_obj=student()
student_obj.name="student1"
student_obj.num=1
student_obj.school=school_obj
直接设置外键的id
在student.objects.create中加
school_id=1
通过获取外键对象设置
obj = school.objects.get(name="school1")
student.objects.create(**{"name":"student2","num":2,"school":obj})
teacher1=teacher.objects.get(id=1)
teacher2=teacher.objects.get(id=2)
student1=student.objects.get(id=1)
student1.teacher.add(teacher1,teacher2)
或
teacher1=teacher.objects.filter(id__gt=1,id__lt=10)
student1=student.objects.get(id=1)
student1.teacher.add(*teacher1)
或
teacher1=teacher.objects.filter(id=1)[0]
student1=student.objects.filter(id__gt=1)
teacher1.student_set.add(*student1)
或
student1=student.objects.filter(id=1)[0]
student1.teacher.add(2)
如果多对多关系的表是自己手动创建的,那么还可以直接添加该表的字段,利用两个外键的方式添加。
先找到,再删除
student1=student.objects.filter(id=1)[0].delete()
由于django的级联删除,其他表中如student_teacher表中有student1的信息的数据也会删除
student1=student.objects.filter(id=1)[0]
student1.teacher.clear()#删除多对多表中student_id为student1的id的数据
student1.teacher.remove(2)#删除多对多表中teacher_id为2的数据
student1.teacher.remove(*list)#这里也可以为一个列表
反向即使用student_set,其他和正向同样道理
student1=student.objects.get(id=2)
student1.name="sfencs"
student1.save()
``
或者
```python
student1=student.objects.filter(id=2).update(name="sfencs")
update是queryset的方法,可以更新多行数据。
save方法是将一行的所有字段都重新存储一遍,update方法只将要改变的字段存储,效率更高。
先删除,再添加
如果查询结果是一个结果集,即QuerySet对象,那么它还有以下方法
if obj:
仍然会执行SQL语句,若使用
if obj.exists():
就可以避免这种问题。
得到对象后,查找字段
student1=student.objects.filter(school_id=1)[0]
print(student1.num)
拿时外键对象的字段
student1 = student.objects.filter(id=2)[0]
print(student1.school.name)
拿多对多关系的字段
因为是多对多关系,得到的会是一个QuerySet对象
student1=student.objects.filter(id=2)[0]
print(student1.teacher.values(‘name‘))
一对多
school_name为外键对象的字段
school为student表中设置的外键字段
student1=student.objects.filter(id=2).values(‘school__name‘)
print(student1)
多对多
和一对多的查询方式一样
teacher为student表中设置的外键字段
student1=student.objects.filter(id=2).values(‘teacher__name‘)
print(student1)
反向一对多
student__name中的student为表名
result=school.objects.filter(student__name=‘student1‘).values(‘name‘)
print(result)
反向多对多
也和反向多对多一样
result=teacher.objects.filter(student__id=2).values(‘name‘)
print(result)
其他查询条件
聚合查询是对QuerySet对象进行计算得到一个结果值作为字典中的值放到一个字典中
这里先引入一些聚合方法
from django.db.models import Avg,Min,Sum,Max
举例:
result=student.objects.all().aggregate(Max(‘num‘))
print(result)
得到的是一个字典:{‘num__max’: 3}
若你想给这个字典的key换一个名字,可以使用:
result=student.objects.all().aggregate(new_name=Max(‘num‘))
输出:{‘new_name’: 3}
也可以同时进行多个聚合查询
result=student.objects.all().aggregate(Avg(‘num‘),Min(‘num‘),new_name=Max(‘num‘))
分组查询就像是SQL语句中的group by
可以如下使用,即以school_id分组,计算每组的max(num)
result=student.objects.values(‘school_id‘).annotate(Max(‘num‘))
也可以对QuerySet对象使用
在查询得出的结果集中进行分组
result=student.objects.filter(school_id__lt=2).values(‘school_id‘).annotate(Max(‘num‘))
执行F查询前还得先引入
from django.db.models import F
F查询可以将对象中的值作为变量使用,例如:
result=student.objects.filter(id__gt=F(‘school_id‘))
或者
result=student.objects.update(num=F(‘school_id‘)+1)
惯例先引入
from django.db.models import Q
Q查询是应用在查询条件上的。
在普通的查询当中,且可以用逗号‘,’表示,可是如果我们想使用或的关系怎么办,使用Q来完成它
student1=student.objects.filter(Q(num=1) | Q(school_id=1))
相当于用Q将条件封装,在Q对象之间使用&或者|或者~
如果想将普通发关键字参数查询与Q查询一起使用,必须将关键字参数查询放到Q的后边
Django 的查询语法难以简练地表达复杂的 WHERE 子句,于是使用扩展查询extra,其原理相当于给SQL语句中添加子语句
extra(select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
这些参数都是可写可不写的
简单举例:
直接暴力上中文了
student1=student.objects.extra(select={‘是否大于2‘:‘num>2‘})
print(student1.values(‘是否大于2‘)[0][‘是否大于2‘])
SQL语句其实执行的是SELECT (num>2) AS 是否大于2
FROM `blog_student
可以为select传递参数
student1=student.objects.extra(select=({‘是否大于2‘:‘num>%s‘}),select_params = (‘2‘,))
可以排序
加‘-’为从大到小,不加为从小到大
student1=student.objects.extra(select=({‘是否大于2‘:‘num>%s‘}),select_params = (‘2‘,))
student1=student1.extra(order_by=[‘-是否大于2‘])
语句中会添加SELECT (num>’2’) AS 是否大于2
FROM blog_student
ORDER BY 是否大于2
DESC
也可以设置where条件,并且给where设置参数
student1=student.objects.extra(select=({‘是否大于2‘:‘num>%s‘}),select_params = (‘2‘,),where=[‘id<%s‘],params=[‘4‘])
SQL语句为SELECT (num>’2’) AS 是否大于2
FROM blog_student
WHERE (id<’4’) ORDER BY 是否大于2
DESC
在setting.py中加上下边的代码
LOGGING = {
‘version‘: 1,
‘disable_existing_loggers‘: False,
‘handlers‘: {
‘console‘:{
‘level‘:‘DEBUG‘,
‘class‘:‘logging.StreamHandler‘,
},
},
‘loggers‘: {
‘django.db.backends‘: {
‘handlers‘: [‘console‘],
‘propagate‘: True,
‘level‘:‘DEBUG‘,
},
}
}
LOGGING
标签:avos mysq ever ref fun 外键约束 blog comment com
原文地址:https://www.cnblogs.com/sfencs-hcy/p/9911526.html