zoukankan      html  css  js  c++  java
  • MySQL:PyMySQL&ORM

    一、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相关操作详细

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

         #高二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
  • 相关阅读:
    175. 组合两个表
    101. 对称二叉树
    292. Nim游戏
    319. 灯泡开关
    155. 最小栈
    232. 用栈实现队列
    225. 用队列实现栈
    145. 二叉树的后序遍历
    144. 二叉树的前序遍历
    【leetcode】977. Squares of a Sorted Array
  • 原文地址:https://www.cnblogs.com/nixindecat/p/9869794.html
Copyright © 2011-2022 走看看