一、PyMySQL介绍
PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。
Django中也可以使用PyMySQL连接MySQL数据库。
pip install pymysql #安装pymysql
二、连接数据库
注意事项
在进行本文以下内容之前需要注意:
- 你有一个MySQL数据库,并且已经启动。
- 你有可以连接该数据库的用户名和密码
- 你有一个有权限操作的database
基本使用
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
# 定义要执行的SQL语句
sql = """
CREATE TABLE USER1 (
id INT auto_increment PRIMARY KEY ,
name CHAR(10) NOT NULL UNIQUE,
age TINYINT NOT NULL
)ENGINE=innodb DEFAULT CHARSET=utf8;
"""
# 执行SQL语句
cursor.execute(sql)
# 关闭光标对象
cursor.close()
# 关闭数据库连接
conn.close()
返回字典格式数据
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句并且将结果作为字典返回的游标
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)#重点在加入括号的这行参数
# 定义要执行的SQL语句
sql = """
CREATE TABLE USER1 (
id INT auto_increment PRIMARY KEY ,
name CHAR(10) NOT NULL UNIQUE,
age TINYINT NOT NULL
)ENGINE=innodb DEFAULT CHARSET=utf8;
"""
# 执行SQL语句
cursor.execute(sql)
# 关闭光标对象
cursor.close()
# 关闭数据库连接
conn.close()
注意:
charset=“utf8”,编码不要写成"utf-8"
三、增删改查操作
增加
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
username = "Alex"
age = 18
# 执行SQL语句
cursor.execute(sql, [username, age])
# 提交事务
conn.commit()
cursor.close()
conn.close()
插入数据失败回滚
在执行增删改操作时,如果不想提交前面的操作,可以使用 rollback() 回滚取消操作。
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
username = "Alex"
age = 18
try:
# 执行SQL语句
cursor.execute(sql, [username, age])
# 提交事务
conn.commit()
except Exception as e:
# 有异常,回滚事务
conn.rollback()
cursor.close()
conn.close()
获取插入数据的ID
(关联操作时会用到)重点!
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
username = "Alex"
age = 18
try:
# 执行SQL语句
cursor.execute(sql, [username, age])
# 提交事务
conn.commit()
# 提交之后,获取刚插入的数据的ID 重点在此处lastrowid
last_id = cursor.lastrowid
except Exception as e:
# 有异常,回滚事务
conn.rollback()
cursor.close()
conn.close()
批量执行
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "INSERT INTO USER1(name, age) VALUES (%s, %s);"
data = [("Alex", 18), ("Egon", 20), ("Yuan", 21)]
try:
# 批量执行多条插入SQL语句 executemany
cursor.executemany(sql, data)
# 提交事务
conn.commit()
except Exception as e:
# 有异常,回滚事务
conn.rollback()
cursor.close()
conn.close()
删除
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
sql = "DELETE FROM USER1 WHERE id=%s;"
try:
cursor.execute(sql, [4])
# 提交事务
conn.commit()
except Exception as e:
# 有异常,回滚事务
conn.rollback()
cursor.close()
conn.close()
修改
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
# 修改数据的SQL语句
sql = "UPDATE USER1 SET age=%s WHERE name=%s;"
username = "Alex"
age = 80
try:
# 执行SQL语句
cursor.execute(sql, [age, username])
# 提交事务
conn.commit()
except Exception as e:
# 有异常,回滚事务
conn.rollback()
cursor.close()
conn.close()
查询
查询单条数据
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
# 查询数据的SQL语句
sql = "SELECT id,name,age from USER1 WHERE id=1;"
# 执行SQL语句
cursor.execute(sql)
# 获取单条查询数据 fetchone
ret = cursor.fetchone()
cursor.close()
conn.close()
# 打印下查询结果
print(ret)
查询多条数据
# 导入pymysql模块
import pymysql
# 连接database
conn = pymysql.connect(host=“你的数据库地址”, user=“用户名”,password=“密码”,database=“数据库名”,charset=“utf8”)
# 得到一个可以执行SQL语句的光标对象
cursor = conn.cursor()
# 查询数据的SQL语句
sql = "SELECT id,name,age from USER1;"
# 执行SQL语句
cursor.execute(sql)
# 获取多条查询数据fetchall
ret = cursor.fetchall()
cursor.close()
conn.close()
# 打印下查询结果
print(ret)
进阶用法
# 可以获取指定数量的数据
cursor.fetchmany(3)
# 光标按绝对位置移动1
cursor.scroll(1, mode="absolute")
# 光标按照相对位置(当前位置)移动1
cursor.scroll(1, mode="relative")
四、ORM(对象关系映射)
orm:
类 ----> 表
对象实例 ----> 表的记录
1、对django模型的配置:
- settings的配置: INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config', 注意查看有无新建的app
] - 更改一下数据库的配置: DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 数据库名称,
'USER': 'root',
'PASSWORD': '',
'CHARSET': 'utf8',
'HOST': '127.0.0.1',
'PORT':3306
}
} - init.py:
import pymysql
pymysql.install_as_MySQLdb()
2、运行如下命令(创建表时):
python3 manage.py makemigrations ====> 生成数据库文件
python3 manage.py migrate ====> 执行生成的数据库文件
3、 Django中 app 中 models.py 如下示例(创建表)
from django.db import models # Create your models here. class classes(models.Model):
id = models.AutoField(primary_key=True)
classname = models.CharField(max_length=32, null=False, default='') class students(models.Model):
#不写id orm 会自动生成一个 id字段
student_name = models.CharField(max_length=32, null=False, default='')
classes = models.ForeignKey('classes', on_delete=None) class test(models.Model):
age = models.IntegerField() class teacher(models.Model):
tname = models.CharField(max_length=32, null=False, default='') class teacher2class(models.Model):
teacher = models.ForeignKey('teacher', on_delete=None)
classes = models.ForeignKey('classes', on_delete=None) #多对多创建另外一种方式
classes = models.ManyToManyField('classes') #不创建关联表 在teacher表加这个字段,Django会自动生成第三张表:PS:建议使用上面的方式,语义直白
4、 Django 中 app 中 views 如下示例
1、添加数据
# models.表对象.objects.方法
models.classes.objects.create(classname='高二1班')
li = [
models.classes(classname='高二5班'),
models.classes(classname='高二3班'),
models.classes(classname='高二6班'),
]
models.classes.objects.bulk_create(li)
2、查询数据
from django.shortcuts import render, HttpResponse
from app01 import models
# Create your views here. # 获取所有的数据=====> select * from classses;
res = models.classes.objects.all()
#<QuerySet [
<classes: classes object (1)>,
<classes: classes object (2)>,
<classes: classes object (3)>,
<classes: classes object (4)>
]>
for item in res:
print(item.id , item.classname) #获取classname ====> select classname from classses;
#<QuerySet [
{'classname': '高二1班'},
{'classname': '高二2班'},
{'classname': '高二3班'},
{'classname': '高二4班'}
]>
res = models.classes.objects.values('classname').all()
print(res)#列表字典格式 for item in res:
print(item['classname']) #value_list:
<QuerySet [('高二1班',), ('高二2班',), ('高二3班',), ('高二4班',)]>
res = models.classes.objects.values_list('classname').all()
print(res) 2.1 取第一条 ---> select * from classes limit 1;
res = models.classes.objects.first()
print(res.classname) 2.2 根据条件查询数据
res = models.classes.objects.filter(id=4)
3. 删除 ---> delete from classes where id=1;
models.classes.objects.filter(id=4).delete()
4. 更新
models.classes.objects.filter(id=3).update(classname='高二10班')
5. 一对多添加
models.students.objects.create(student_name='王刚蛋', classes_id=1)
models.students.objects.create(student_name='王铁锤', classes_id=2)
models.students.objects.create(student_name='二狗', classes_id=3)
models.students.objects.create(student_name='刘dd', classes_id=1)
models.students.objects.create(student_name='狗剩子', classes_id=2)
models.students.objects.create(student_name='铁蛋', classes_id=3)
models.students.objects.create(student_name='xxxx', classes_id=3)
6.正向查询
# 外键(FK) classes_id 代指 ---> classes表里面的一行记录
# sql :select * from classes left join students on claess.id =stdents.classid;
# res.query:SELECT `app01_students`.`id`, `app01_students`.`student_name`, `app01_students`.`classes_id` FROM `app01_students`
res = models.students.objects.all()
for item in res:
print(item.id, item.student_name, item.classes.classname)#此处classes为建表时的外键名称
7. 反向查询
#高二1班有多少学生? obj.表名_set.all()
sql : select * from classes where classname='高二1班'
7.1先查询班级表 班级名为高二1班的
res = models.classes.objects.filter(classname='高二1班').first()
7.2再查询学生表中所有符合的
info = res.students_set.all()
# select * from students where classes_id = res['id']
print(info)
for item in info:
print(item.student_name)
8. __ 神奇的双下划线
res = models.students.objects.filter(classes__classname='高二1班').all()
#相当于执行下面的sql语句,连表查询妙用
print(res.query)
#SELECT `app01_students`.`id`,
`app01_students`.`student_name`,
`app01_students`.`classes_id`
FROM `app01_students` INNER JOIN `app01_classes` ON (`app01_students`.`classes_id` = `app01_classes`.`id`) WHERE `app01_classes`.`classname` = 高二1班
for item in res:
print(item.student_name)
9. 获取个数 ---> count() ==> select count(*) from students
cnt = models.classes.objects.count()
print(cnt)
10. 大于,小于
greater then 大于
res = models.classes.objects.filter(id__gt=1) #大于
res = models.classes.objects.filter(id__gte=1)#大于等于
res = models.classes.objects.filter(id__lt=1) #小于
res = models.classes.objects.filter(id__lte=1)#小于等于
sql :select * from classes where id < 10 and id > 1
res = models.classes.objects.filter(id__lt=10, id__gt=1) # 获取id小于10 且 大于1的值
11. in 判断在不在
exclude : 除去xxx ,还剩xxxx
res = models.classes.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
res = models.classes.objects.exclude(id__in=[11, 22, 33]) # not in
12. isnull
res = models.classes.objects.filter(id__isnull=True)
13. contains 模糊查询
select * from stundets where student_name like '%二%';
contains 相当于 like
startswith == > like 'ven%',istartswith, endswith ===> like '%ven', iendswith,
res = models.classes.objects.filter(classname__contains="ven")
res = models.classes.objects.filter(classname__icontains="ven") # icontains大小写不敏感(不区分大小写)
models.classes.objects.exclude(classname__icontains="ven") #判断字符中没有ven 的数据
14. range 范围
res = models.classes.objects.filter(id__range=[1, 2]) # 范围bettwen and
15. order by 排序
models.classes.objects.filter(name='seven').order_by('id') # asc 升序
models.Tb1.objects.filter(name='seven').order_by('-id') # desc 降序
16. group by 分组查询
from django.db.models import Count, Min, Max, Sum
res = models.students.objects.values('classes_id').annotate(c=Count('id')) #根据classes_id分组
SELECT `app01_students`.`classes_id`,
COUNT(`app01_students`.`id`) AS `c` FROM `app01_students` GROUP BY `app01_students`.`classes_id` ORDER BY NULL
17. limit、offset 切片
res = models.students.objects.all()[10:20] #从第10行开始取:取20条
print(res.query)
18. F F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
from django.db.models import F
#对id=1的人 在age字段上 数据+1
models.students.objects.filter(id=1).update(age=F('age') + 1) #对两个字段的值做比较和操作
19. Q 执行更复杂的查询(或例如OR语句),你可以使用Q对象
from django.db.models import F, Q Q(nid=8) | Q(nid__gt=10)
res = models.students.objects.filter(Q(id=8) | Q(id__gt=10)) #取id=8 或者 id>10 的数据
print(res.query)
# SELECT `app01_students`.`id`, `app01_students`.`student_name`, `app01_students`.`classes_id` FROM `app01_students` WHERE (`app01_students`.`id` = 8 OR `app01_students`.`id` > 10) Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
#取id=8 或者 id>10 并且 名字为root 的 数据
res = models.students.objects.filter(Q( Q(id=8) | Q(id__gt=10)) & Q(student_name='root'))
print(res.query)
20. 执行原生SQL Django的orm无法满足时
from django.db import connection, connections #一个连接默认数据库,一个可以选择数据库
cursor = connection.cursor() #connection会去settings找数据库配置
cursor = connections['xxx'].cursor() #这是连接另一个主机的方式 cursor.execute("""SELECT * from auth_user where id = %s""", [1])
res = cursor.fetchone()
.
.
21. 多对多查询
1. 反向查询:
res = models.teacher.objects.filter(tname='eagon').first()
1、obj.表类名小写_set.all()
info = res.teacher2class_set.all() #查询老师名为eagon 所代课的 班级名
2、在models中的表类的ForeignKey('teacher', on_delete=None,related_name = 'classes')
info = res.classes.all()
for item in info:
item.classes.classname 2. 神器的双下滑线查询
res = models.teacher2class.objects.filter(teacher__tname='eagon')
for item in res:
item.classes.classname
最后补充 Djangoadmin 的配置 (admin是Django自带的一个后台管理系统)
- admin.py中,注册表
- admin.site.register(models.表名)
- urls 中
- url('admin', admin.site.urls)
- 命令行创建
- python3 manage.py createsupperuser