一、 简介

1. 程序设计到数据库相关操作时,一般处理流程如下:

  1. 创建数据库,设计表结构和字段;
  2. 使用MySQLdb来连接数据库,编写数据访问层代码;
  3. 业务逻辑层去调用数据访问层执行数据库操作(增删改查)。

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)

我试了下只能对数字操作,字符串操作不可行。

如有不足,欢迎指正!