一、 简介
1. 程序设计到数据库相关操作时,一般处理流程如下:
- 创建数据库,设计表结构和字段;
- 使用MySQLdb来连接数据库,编写数据访问层代码;
- 业务逻辑层去调用数据访问层执行数据库操作(增删改查)。
2. ORM:Object Relational Mapping(关系对象映射)
类 名: 数据库中的表名
类属性: 数据库中的字段
类实例: 数据库表中的一行数据
obj.id:类实例对象的属性
3. 优势
使用Django开发项目无需关心程序底层使用的数据库是MySQL、Oracle…,如果数据库迁移,只需要更换Django的数据库引擎即可。
二、 Django连接MySQL
1. 创建数据库
CREATE DATABASE `db_name` default charset utf8 COLLATE utf8_general_ci;
2. 修改数据库配置
project的setting.py设置,连接MySQL数据库(Django默认使用的是sqllite数据库)
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'db_name', # 数据库名字
'USER': 'root', # 用户名
'PASSWORD': 'mysql', # 数据库密码
'HOST': 'localhost', # 主机名
'PORT': '3306', # mysql端口
}
}
3. 修改project的__init__.py文件
设置Django默认连接MySQL的方式
import pymysql
pymysql.install_as_MySQLdb()
4. setting中注册APP
INSTALLED_APPS = [
'app_name',
]
5. models.py创建表
from django.db import models
class Users(models.Model):
'''用户模型'''
id = models.AutoField(priamry_key=True)
username = models.CharField(max_length=32, unique=True)
password = models.CharField(max_length=32, default='12345678')
date_joined = models.DateField(auto_now_add=True)
...
# 枚举字段:
choice=(
(1,'男'),
(2,'女')
)
lover=models.IntegerField(choices=choice)
# 枚举比外键的优势:
# 1. 无需连表查询性能低,省磁盘空间(选项不固定时使用外键)
# 2. 在model文件里不能动态添加(选项不变用Django的choice)
# 外键字段:
# 一对一:OneToOneField
# 多对多:ManyToManyField
6. 进行数据本地初始化和数据迁移
python manage.py makemigrations app_name
python manage.py migrate
三、数据操作
1. 增
方式一: model_name.objects.create()
User.objects.create(username=xxx, password=xxx, mobile=xxx)
方式二: 类实例化:obj=类(属性=xx) obj.save()
user_obj=User(username=xxx, password=xxx, mobile=xxx)
user_obj.save()
2. 删
User.objects.filter(username=xxx).delete()
3. 改
方式一: update()
User.objects.filter(id=xxx).update(username=xxx, password=xxx, mobile=xxx)
方式二:obj.save()
user_obj=User.objects.get(id=xxx)
user_obj.price=5
user_obj.save()
4. 查
以下查询偏高级,除了查询集,其他查询语句直接转换成列表或字典或值,去掉外层的查询集 QuerySet。
1.对于单条数据查询
(1)查询某条数据(对象):
User.objects.filter(username='user1')
查询结果(查询集):<QuerySet [<User: user1>]>
如果查询不到返回空集:<QuerySet []>
注意:如果查询语句后边加first()
a = User.objects.filter(username='user1').first()
查询失败返回None,查询成功返回user1,可使用a.mobile获取user1的手机号
但不加first返回的是查询集,不可以使用a.mobile获取,否则报错,获取user1的单个数据请看下面的查询语句
至于需不需要加first,看自己需求和代码量。
(2)查询某条数据的所有信息:
list(User.objects.filter(username='user1').values())[0]
查询结果:{'id': 1, 'username': 'user1', 'email': 'user1@163.com', 'mobile': '13600001111'}
(3)查询某条数据的某个信息,与该字段组成kv形式:
list(User.objects.filter(username='user1').values("username"))[0]
查询结果:{'username': 'user1'}
(4)查询某条数据的某个信息:
User.objects.filter(username='user1').values()[0]['mobile']
查询结果:13600001111
(5)判断是否存在某条数据:
User.objects.filter(username='user1')
使用 filter() 方法查询成功返回查询集,查询不存在返回空,不报错;
User.objects.get(username='user1')
使用 get() 方法需要加判断或捕获异常,查询成功返回user1,查询不存在则报错。
(6)查询第一条数据:
Users.objects.first()
(7)查询最后一条数据:
Users.objects.last() 但这种写法我自测的结果还是取了第一条,所以该方法不靠谱。
解决:
(1)查询所有的数据,放到列表中,然后取最后一条数据:
qry = list(Users.objects.all())[-1]
(2)按id倒排后取第一条获得最后一条数据:
Users.objects.all().order_by('-id').first()
两种方法都返回最后一条:user400
可以使用qry.mobile
获取该用户的手机号。
因为id是自增的,id最大的肯定是最新添加进去的,也就是最后一条。当然,正的id也可以取到第一条。
- 野路子方式不推荐:
- 获取某条数据:list(User.objects.all())[2] 结果:user3
- 获取某条数据的某个值:list(User.objects.all())[2].mobile 结果:13600001111
2. 对于多条数据查询
(1)获取两个数据,username为k,mobile为v,组成字典形式:
dict(list(User.objects.all().only("username", "mobile").values_list("username", "mobile")))
查询结果:{'user1': '13600001111', 'user2': '13600001111', 'user3': '13600001111'}
(2)获取n个数据,放到列表中:
list(Users.objects.all().only("username", "mobile", 'status').values_list("username", "mobile", 'status'))
查询结果:[('user1', '13600001111', '1'), ('user2', '13600001111', '1'), ('user3', '13600001111', '0')]
3. 对于整表数据查询
(1)获取所有用户:
User.objects.all()
查询结果:<QuerySet [<User: user1>, <User: user2>, <User: user3>]>
(2)获取所有用户的所有信息:
list(User.objects.all().values())
查询结果:[{'id': 1, 'username': 'user1', 'email': 'user1@163.com', 'mobile': '13600001111'}, {'id': 2, 'username': 'user2', 'email': 'user2@163.com', 'mobile': '13600001111'}, {'id': 3, 'username': 'user3', 'email': 'user3@163.com', 'mobile': '13600001111'}]
(3)获取某列值,放到一个列表中:
list(User.objects.all().only("username").values_list("username", flat=True))
查询结果:['user1', 'user2', 'user3']
(4)获取某列值,字段值为k,值为v:
list(User.objects.all().values('username'))
查询结果:[{'username': 'user1'}, {'username': 'user2'}, {'username': 'user3'}]
(5)获取该表的数据条数
User.objects.count()
返回结果:400
4. 范围查询 in 、 not in 、 range
(1)in 查询多条数据: 字段名__in=[xxx]
User.objects.filter(username__in=['user1', 'user2']).all()
查询结果:<QuerySet [<User: user1>, <User: user2>]>
如果想要所有信息,则在最后加values();如果想去掉外层查询集则用list()包裹起来。
(2)not in 查询不含某些条数据的其他数据:exclude(字段名__in=[xxx]).all()
User.objects.all().exclude(username__in=['user1', 'user2']).all()
查询结果:<QuerySet [<User: user3>, <User: user4>, <User: user5>, <User: user6>, <User: user7>, <User: user8>, <User: user9>, <User: user10>, <User: user11>, <User: user12>]>
(3) range 按区间查询一段数据:字段名__range=[start, end] 闭区间
User.objects.filter(id__range=[1, 4]).all()
查询结果:<QuerySet [<User: user2>, <User: user3>, <User: user4>, <User: user5>]>
(4) 切片 查询一段区间内的数据 前开后闭
User.objects.all()[1: 5]
查询结果:<QuerySet [<User: user2>, <User: user3>, <User: user4>, <User: user5>]>
5. 比较符号(大于、小于、大于等于、小于等于)
(1)大于:字段名__gt
User.objects.filter(id__gt=5).all()
查询结果:<QuerySet [<User: user6>, <User: user7>, <User: user8>, <User: user9>, <User: user10>]>
(2)小于:字段名__lt
User.objects.filter(id__lte=5).all()
查询结果:<QuerySet [<User: user1>, <User: user2>, <User: user3>, <User: user4>, <User: user5>]>
(3)大于等于:字段名__gte
User.objects.filter(id__gte=5).all()
(4)小于等于:字段名__lte
User.objects.filter(id__lte=5).all()
6. 排序查询
(1)order_by(xxx),默认正序排列,前边加“-”则降序排列
Users.objects.all().order_by('id').all()
查询结果:<QuerySet [<User: user1>, <User: user2>, <User: user3>, <User: user4>, <User: user5>]>
Users.objects.all().order_by('-id').all()
查询结果:<QuerySet [<User: user5>, <User: user4>, <User: user3>, <User: user2>, <User: user1>]>
(2)取某一段数据进行排序
User.objects.filter(id__range=[101, 107]).order_by('id').all()
查询结果:<QuerySet [<User: user1>, <User: user2>, <User: user3>, <User: user4>, <User: user5>, <User: user6>, <User: user7>]>
7. 模糊查询 like
(1)查询用户名包含’user1’的所有用户,使用 字段名__contains=‘xxx’ 进行过滤查询
User.filter(username__contains='user1').all()
后边.all()不加也可以返回,但最好加上
查询结果:<QuerySet [<User: user1>, <User: user10>, <User: user11>, <User: user12>, <User: user13>, <User: user14>, <User: user15>, <User: user16>, <User: user17>, <User: user18>]>
(2)查询用户名包含’user1’的所有用户的所有信息,放到列表中:字段名__contains='xxx’
list(User.objects.filter(username__contains='user1').all().values())
查询结果:[{'id': 2, 'username': 'user1', 'email': 'user1@163.com', 'mobile': '13600001111'}, {'id': 9, 'username': 'user10', 'email': 'user10@163.com', 'mobile': '13600001111'}, {'id': 10, 'username': 'user11', 'email': 'user11@163.com', 'mobile': '13600001111'}, {'id': 11, 'username': 'user12', 'email': 'user12@163.com', 'mobile': '13600001111'}...]
(3)查询用户名包含’user1’的所有用户的某个数据(username),与其字段值组成kv放到列表中
list(User.objects.filter(username__contains='user1').all().values('username'))
查询结果:[{'username': 'user1'}, {'username': 'user10'}, {'username': 'user11'}, {'username': 'user12'}, {'username': 'user13'}, {'username': 'user14'}, {'username': 'user15'}...]
(4)查询用户名包含’user1’的所有用户的某个数据(username)不想要字典,直接得到用户列表,则执行:
list(User.objects.filter(username__contains='user1').all().values_list('username', flat=True))
查询结果:['user1', 'user10', 'user11', 'user12', 'user13', 'user14', 'user15', 'user16', 'user17'...]
(5)获取某列除特定值以外的值 exclude,放到列表中,使用 字段名__in
list(User.objects.all().exclude(username__in=['user1', 'user2']).values_list('username', flat=True))
查询结果:['user3', 'user4', 'user5']
(6)查询某个字段值以xx开头的所有数据:字段名__startswith=xxx
User.objects.filter(username__startswith='us')
返回查询集
(7)查询某个字段值以xx结尾的所有数据:字段名__endswith=xxx
User.objects.filter(username__endswith='1')
返回查询集
* Q查询前边加~表示否定:User.objects.filter(~Q(username__endswith='1')) 表示username不以1结尾
(8)默认查询所有信息,如果有特定查询信息则查询满足要求的数据:
user_obj = Tasks.objects.all()
if username:
user_obj = user_obj.filter(username__contains=username).all()
应用场景:用户展示页,加入搜索功能,如果多个查询条件,继续向下if判断然后拼接查询语句即可。
8. 逻辑符 and、or
(1)and:filter(id=1, username=‘user1’)
User.objects.filter(id=1, username='user1')
(2) or:Q方法
| 表示 “或”; & 表示 “与”
from django.db.models import Q
User.objects.filter(Q(id=1) | Q('username'='user1'))
如果含有多个“或”(或“与”条件)条件,可继续往后拼接 Q()
查询结果:<QuerySet [<Users: user1>]>
9. F()方法
作用:更新数据时先从数据库中将原数据取出后放在内存中,然后修改相应的字段值,最后再提交。
使用前先引入:
from django.db.models import F
(1)比如要更新user1的年龄,加一岁:
user_obj = User.objects.filter(username='user1')
user_obj.age += 1
user_obj.save()
(2) 比如要让一个字段(age)整体加1
User.objects.update(F('age') + 1)
我试了下只能对数字操作,字符串操作不可行。
如有不足,欢迎指正!