0. 简介

ORM:Object Relational Mapping(关系对象映射)

1
2
3
4
5
6
7
类名对应  →  数据库中的表名

类属性对应 → 数据库里的字段

类实例对应 → 数据库表里的一行数据

obj.id obj.name → 类实例对象的属性

Django orm的优势:

Django的orm操作本质上会根据对接的数据库引擎,翻译成对应的sql语句;所有使用Django开发的项目无需关心程序底层使用的是MySQL、Oracle、sqlite….,如果数据库迁移,只需要更换Django的数据库引擎即可;

1. 配置

  1. ORM没有创建数据库功能,因此我们首先要自己创建一个数据库。
1
> create database djangotestdb2 default character set utf8 collate utf8_general_ci;
  1. 修改project中的settings.py文件中设置 连接 MySQL数据库(Django默认使用的是sqllite数据库)
1
2
3
4
5
6
7
8
9
10
11
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'...',
'USER': '...',
'PASSWORD': '...',
'HOST': 'localhost', # 连接的主机地址
'PORT': '3306',
}
}

​ 扩展:查看orm操作执行的原生SQL语句,在project中的settings.py文件增加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
  1. 修改project 中的__init__py 文件设置 Django默认连接MySQL的方式
1
2
3
4
import pymysql

pymysql.version_info = (1, 4, 13, "final", 0)
pymysql.install_as_MySQLdb()
  1. setings文件注册APP
1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'manageapp1',
]

2. 增删改查

  1. 在app的models.py创建表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class UserInfo(models.Model):       # 必须继承
# 自增bitint型主键,若没有时Django会自动创建int型自增id
nid = models.BigAutoField(primary_key = True)
# char类型
username = models.CharField(max_length = 32)
password = models.CharField(max_length = 64)

age = models.IntegerField(null=True)
# age = models.IntegerField(default=1)
# 可以为空或指定默认值,防止增加字段时数据库有数据而报错
ug = models.ForeignKey("UserGroup",null=True, on_delete=models.CASCADE)
# 变为ug_id

class UserGroup(models.Model):

title = models.CharField(max_length = 32)
  1. 进行数据迁移
1
2
3
4
python manage.py makemigrations  #把你写在models中的代码翻译成增、删、改的 SQL 语句;

python manage.py migrate #把orm代码转换成的sql语句去数据库执行
python manage.py migrate --fake #只记录变化,不提交数据库操作

数据操作

1
from manageapp1 import models

增加:

1
2
3
models.UserGroup.objects.create(title="销售部")
models.UserInfo.objects.create(username='root',password='pwd',age=18,ug_id=1) # 注意是ug_id
models.UserGroup.objects.filter(id=1).create(**dict) # 传入字典,更适合于批量操作,与Form组件搭配

删除:

1
models.UserGroup.objects.filter(id=1).delete() 

更改:

1
2
3
4
models.UserGroup.objects.filter(id=1).update(title="公关部") 
models.UserGroup.objects.filter(id=1).update(**dict)
# 传入字典,更适合于批量操作
models.UserGroup.objects.filter(id=1).filter(**{'id':1,'name':'alex'})

查找:

​ 查找多项数据与跨表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 1. 返回值QuerySet类型(object对象列表)
group_list = models.UserInfo.objects.all()
for row in group_list:
print(row.id, row.title, row.ug_id)
print(row.ug.title) # ug代表UserGroup中的一行,因此这样可以联表操作

# 2. 返回值[{'id':1,'username':},{..}]
group_list = models.UserInfo.objects.all().values('id','username','ug__title')
for row in group_list:
print(row['id'],row[ug__title]) # 在遍历值时就进行跨表操作

# 3. 返回值 [(1,'..','..'),(2,'..','..')]
group_list = models.UserInfo.objects.all().values_list('id','username','ug__title')
for row in group_list:
print(row[0],row[2]) # 在遍历值时就进行跨表操作

​ 条件查找:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
group_list = models.UserGroup.objects.filter(id=1)  # where id = 1
group_list = models.UserGroup.objects.filter(id=1,name='xx') # where id = 1 and name=xx
group_list = models.UserGroup.objects.filter(id__gt=1) # where id > 1
group_list = models.UserGroup.objects.filter(id__gte=1) # where id >= 1
group_list = models.UserGroup.objects.exclude(id=1) # where id ≠ 1
group_list = models.UserGroup.objects.filter(id__gt=1).first()
group_list = models.UserGroup.objects.filter(id__lt=1) # where id < 1
group_list = models.UserGroup.objects.filter(id__in=[1,2,3]) # where id in [1,2,3]
group_list = models.UserGroup.objects.filter(id__range=[1,2]) # where 1<=id<=2
group_list = models.UserGroup.objects.filter(name__startswith='xxx')
group_list = models.UserGroup.objects.filter(name__contains='xxx')
models.UserGroup.objects.all().count() # 数量
models.UserGroup.objects.all()[1:19] # 片选
# 跨表:
# 1. 正向
xxx.filter('ug__title'='超级用户').values('id','name','ut__title')
# 2. 反向
xxx.filter('表名__title'='超级用户').values('id','name','表名__title')

​ 正反向查找:

1
2
3
4
5
6
7
# 正向寻找:一对一       反向寻找:一对多
for obj in models.UserGroup.objects.all():
for link in obj.userinfo_set.all(): # 反向查找:关联表名小写_set.all() -> object列表
print(link.username, link.ug_id)

for obj in models.UserGroup.objects.values('id','title','userinfo'):
print(obj)

其他

  1. 排序
1
2
user_list = models.UserGroup.objects.all().order_by('id','name')
# 按id升序排,id相同按name升序,加'-'变降序
  1. F
1
2
3
from django.db.models import F
models.UserInfo.objects.all().updata(age=F('age')+1)
# F('age')表示数据库原始值,上述语句将表内所有age=age+1
  1. Q (用于构造复杂查询条件)
1
2
3
from django.db.models import Q
models.UserInfo.objects.filter(Q(id=8) | Q(id=9))
# 实现或操作查询

​ 以对象的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
q1 = Q()
q1.connector = 'OR'
q1.children.append(('id', 1))
q1.children.append(('id', 10))

q2 = Q()
q2.connector = 'OR'
q2.children.append(('c1', 1))
q2.children.append(('c1', 10))

con = Q()
con.add(q1, 'AND')
con.add(q2, 'AND')
models.Tb1.objects.filter(con)
## 相当于 (id=1 or id=10) and (c1=1 or c1=10)
  1. extra(额外的查询条件以及相关表、排序等)
1
2
3
4
5
extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])
  1. 原生SQL语句
1
2
3
4
from django.db import connection, connections
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
row = cursor.fetchone()
  1. 简单的操作

https://www.cnblogs.com/wupeiqi/articles/6216618.html