一、PyMySQL介绍

PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。

Django中也可以使用PyMySQL连接MySQL数据库。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
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(对象关系映射)

        https://www.cnblogs.com/liwenzhou/p/8660826.html              https://www.cnblogs.com/liwenzhou/p/8688919.html             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='周末一期')
    li = [
        models.classes(classname='周末二期'),
        models.classes(classname='周末三期'),
        models.classes(classname='周末四期'),
    ]
    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': '周末一期'},
          {'classname': '周末二期'},
          {'classname': '周末三期'},
          {'classname': '周末四期'}
     ]>
    res = models.classes.objects.values('classname').all()
    print(res)#列表字典格式

    for item in res:
        print(item['classname'])


    #value_list:
        <QuerySet [('周末一期',), ('周末二期',), ('周末三期',), ('周末四期',)]>
    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='周末3期')

5. 一对多添加

MySQL:PyMySQL&ORM Mysql 第1张
    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)
View Code

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. 反向查询

     #周末一期有多少学生? obj.表名_set.all()
    sql : select * from classes where classname='周末一期'
        7.1先查询班级表 班级名为周末一期的
        res = models.classes.objects.filter(classname='周末一期').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='周末一期').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` = 周末一期
    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
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄