Python主流框架Django,ORM框架

数据模型的增删改查

一、 框架基本介绍

O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。

ORMDjango框架中的使用

django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。

  • 使用 django 框架进行数据库开发的步骤

    • 配置数据库连接信息
    • models.py中定义模型类
    • 数据库迁移
    • 通过操作类和对象完成对数据的增删改查操作

二、ORMDjango中的使用步骤

1-创建工程并修改配置参数

2-安装并注册应用 books

3-配置数据库连接信息

安装MySQL数据库驱动程序

python 复制代码
pip install PyMySQL

在Django的工程同名子目录的__init__.py文件中添加如下语句,作用是让Django的ORM能以MySQLdb的方式来调用pyMySQL

python 复制代码
from pymysql import install_as_MySQLdb
​
install_as_MySQLdb()

在工程配置文件settings.py中修改DATABASES的配置信息

python 复制代码
# django支持多数据库操作,在数据库迁移时默认使用 'default'数据库,想要在迁移时指定使用的数据库见【附2: ORM补充】
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 5000,  # 数据库端口
        'USER': 'django',  # 数据库用户名
        'PASSWORD': 'django',  # 数据库用户密码
        'NAME': 'django_demo'  # 数据库名字
    },
    'bak': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库从机
        'PORT': 5000,  # 数据库端口
        'USER': 'django',  # 数据库用户名
        'PASSWORD': 'django',  # 数据库用户密码
        'NAME': 'django_demo_bak'  # 数据库名字
    },
    
}

修改配置

python 复制代码
DATABASES = {
    "default": {
        'ENGINE': 'dj_db_conn_pool.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 5000,  # 数据库端口
        'USER': 'django',  # 数据库用户名
        'PASSWORD': 'django',  # 数据库用户密码
        'NAME': 'django_demo'  # 数据库名字
        'POOL_OPTIONS': {
            'POOL_SIZE': 10,  # 最小
            'MAX_OVERFLOW': 10,  # 在最小的基础上,还可以增加10个,即:最大20个。
            'RECYCLE': 24 * 60 * 60,  # 连接可以被重复用多久(单位:秒),超过会重新创建,-1表示永久。
            'TIMEOUT':30, # 池中没有连接最多等待的时间(单位:秒)。
        }
    }
}

在MySQL创建数据库

python 复制代码
create database django_demo default charset=utf8;

使用root账户为这个项目创建一个MySQL管理员账户,管理项目相关的数据库

python 复制代码
# 当前ubuntu虚拟机的mysql数据库root密码为:Root123
# 创建用户账号 django, 密码 django (由identified by 指明)
create user django identified by 'django'; 
​
# 授权django_demo数据库下的所有表(django_demo.*)的所有权限(all)给用户django在以任何ip访问数据库('django'@'%')
grant all on django_demo.* to 'django'@'%'; 
​
# 刷新生效用户权限
flush privileges;

4-在books应用下的 models.py 文件中定义模型类

  • 4.1 - 模型类定义规

  • 模型类如果未指明表名,Django默认以 "小写app应用名_小写模型类名" 为数据库表名。可通过在模型类中嵌套定义一个类名为 "Meta" 的类, 并在Meta类中通过类属性 db_table 指明数据库表名.

  • 数据库表名

    • 关于主键 django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。 默认创建的主键列属性为id,可以使用pk(primary key)代替
  • 4.2 - 属性命名限制

    • 不能是python的保留关键字。

    • 不允许使用连续的下划线,这是由Django的查询方式决定的。

    • 定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下属性=models.字段类型(选项)

  • 4.3 - 字段类型

    类型 说明
    AutoField 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性
    BooleanField 布尔字段,值为True或False
    NullBooleanField 支持Null、True、False三种值
    CharField 字符串,参数max_length表示最大字符个数
    TextField 大文本字段,一般超过4000个字符时使用
    IntegerField 整数
    DecimalField 十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数
    FloatField 浮点数
    DateField 日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误
    TimeField 时间,参数同DateField
    DateTimeField 日期时间,参数同DateField
    FileField 上传文件字段
    ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片
  • 4.4 - 选项

    选项 说明
    verbose_name 用于设置该字段在Django管理后台中显示的人类可读的名称。通常用于提供更友好、可读性更强的字段名,以便开发者和管理员更容易理解字段的用途。
    null 如果为True,表示允许为空,默认值是False
    blank 如果为True,则该字段允许为空白,默认值是False
    db_column 字段的名称,如果未指定,则使用属性的名称
    db_index 若值为True, 则在表中会为此字段创建索引,默认值是False
    default 默认
    primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用
    unique 如果为True, 这个字段在表中必须有唯一值,默认值是False
    max_length 字符长度;必选项
    auto_now_add 创建时,自动生成时间
    auto_now 更新时,自动更新为当前时间
    choices 一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。如SEX_CHOICES= (('F', 'Female'), ('M','Male'),)
    • null是数据库范畴的概念,blank是表单验证范畴的
  • 4.5 - 外键

  • 在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:

    • CASCADE 级联,删除主表数据时连同一起删除外键表中数据

    • PROTECT 保护,通过抛出**ProtectedError**异常,来阻止删除主表中被外键应用的数据

    • SET_NULL 设置为NULL,仅在该字段null=True允许为null时可用

    • SET_DEFAULT 设置为默认值,仅在该字段设置了默认值时可用

    • SET() get_or_create作用 get_user_model作用 设置为特定值或者调用特定方法,如

python 复制代码
  from django.conf import settings
  from django.contrib.auth import get_user_model
  from django.db import models
  
  def get_sentinel_user():
      return get_user_model().objects.get_or_create(username='deleted')[0]
  
  class MyModel(models.Model):
      user = models.ForeignKey(
          settings.AUTH_USER_MODEL,
          on_delete=models.SET(get_sentinel_user),
      )
5-以**【图书-英雄管理】** 为例进行 模型类定义与使用演示
  • 创建应用books ,在models.py 文件中定义模型类。

    python 复制代码
    from django.db import models
    ​
    #定义图书模型类BookInfo
    class BookInfo(models.Model):
        btitle = models.CharField(max_length=20, verbose_name='名称')
        bpub_date = models.DateField(verbose_name='发布日期')
        bread = models.IntegerField(default=0, verbose_name='阅读量')
        bcomment = models.IntegerField(default=0, verbose_name='评论量')
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
        
        class Meta:
            # 指明数据库表名
            db_table = 'tb_books'
            # 在admin站点中显示的名称
            verbose_name = '图书'
            # 显示的复数名称
            verbose_name_plural = verbose_name
            
        def __str__(self):
            """定义每个数据对象的显示信息"""
            return self.btitle
        
        
    #定义英雄模型类HeroInfo
    class HeroInfo(models.Model):
        GENDER_CHOICES = (
            (0, 'male'),
            (1, 'female')
        )
        hname = models.CharField(max_length=20, verbose_name='名称') 
        hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  
        hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') 
        hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
        is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
        
        class Meta:
            db_table = 'tb_heros'
            verbose_name = '英雄'
            verbose_name_plural = verbose_name
            
        def __str__(self):
            return self.hname
  • 数据库迁移

    • 数据库迁移说明

    • 进行数据库迁移的目的是将模型类同步到数据库中。makemigrations 命令查找所有可用的模型,为任意一个在数据库中不存在对应数据表的模型创建迁移脚本文件。migrate 命令则运行这些迁移来自动创建数据库表。还提供可选的更丰富的控制模式。

    • 生成迁移文件

      python 复制代码
      python manage.py makemigrations
    • 数据库迁移

      python 复制代码
      python manage.py migrate
      # 指定连接的数据库,默认为default
      python manage.py migrate --database=default
      python manage.py migrate --database=bak
      # 指定迁移的应用
      python manage.py migrate app01 --database=default
      添加测试数据
      
      添加图书数据
      
      
      
      
      
      insert into tb_books(btitle,bpub_date,bread,bcomment,is_delete) values
      ('射雕英雄传','1980-5-1',12,34,0),
      ('天龙八部','1986-7-24',36,40,0),
      ('笑傲江湖','1995-12-24',20,80,0),
      ('雪山飞狐','1987-11-11',58,24,0);
      添加英雄数据
      
      
      
      
      
      insert into tb_heros(hname,hgender,hbook_id,hcomment,is_delete) values
      ('郭靖',1,1,'降龙十八掌',0),
      ('黄蓉',0,1,'打狗棍法',0),
      ('黄药师',1,1,'弹指神通',0),
      ('欧阳锋',1,1,'蛤蟆功',0),
      ('梅超风',0,1,'九阴白骨爪',0),
      ('乔峰',1,2,'降龙十八掌',0),
      ('段誉',1,2,'六脉神剑',0),
      ('虚竹',1,2,'天山六阳掌',0),
      ('王语嫣',0,2,'神仙姐姐',0),
      ('令狐冲',1,3,'独孤九剑',0),
      ('任盈盈',0,3,'弹琴',0),
      ('岳不群',1,3,'华山剑法',0),
      ('东方不败',0,3,'葵花宝典',0),
      ('胡斐',1,4,'胡家刀法',0),
      ('苗若兰',0,4,'黄衣',0),
      ('程灵素',0,4,'医术',0),
      ('袁紫衣',0,4,'六合拳',0);
6-通过类和对象完成数据增删改查操作
  • shell 工具的使用

    复制代码
    Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试python语句。
    • 在终端(Terminal)中进入shell交互环境

      python 复制代码
      python manage.py shell
    • 导入两个模型类,以便后续使用

      python 复制代码
      from books.models import BookInfo, HeroInfo
  • 查看MySQL数据库日志

    • 查看mysql数据库日志可以查看对数据库的操作记录。 mysql日志文件默认没有产生,需要做如下配置:

      python 复制代码
      sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
    • 把68,69行前面的#去除,然后保存并使用如下命令重启mysql服务

      复制代码
      # 跳转到指定行: 在命令行模式下输入":行数"
      复制代码
      sudo service mysql restart
    • 使用如下命令打开mysql日志文件。

      复制代码
      # 实时查看数据库的日志内容
      复制代码
      sudo tail -f /var/log/mysql/mysql.log 
  • 数据库 增、删、改、查

    • 1 - 增加

      • 使用说明

        复制代码
        增加数据有两种方法。
        复制代码
        方式一: 通过创建模型类对象,执行对象的save()方法保存到数据库中。
        复制代码
        方式二: 通过模型类.objects.create()保存。
        复制代码
        ​**可通过IDE自带的数据库插件连接数据库; 方便查看数据库数据变化、执行SQL语句
      • 代码示例

        python 复制代码
        >>> from datetime import date
        >>> book = BookInfo(
            btitle='西游记',
            bpub_date=date(1988,1,1),
            bread=10,
            bcomment=10
        )
        >>> book.save()
        >>> hero = HeroInfo(
            hname='孙悟空',
            hgender=0,
            hbook=book
        )
        >>> hero.save()
        >>> hero2 = HeroInfo(
            hname='猪八戒',
            hgender=0,
            hbook_id=book.id
        )
        >>> hero2.save()
        ​
        ​
        >>> # 指定数据库: HeroInfo.objects.using("bak").create()
        >>> HeroInfo.objects.create(
            hname='沙悟净',
            hgender=0,
            hbook=book
        )
        <HeroInfo: 沙悟净>
        ​
        >>> # 批量创建; batch_size 指定一次性提交的数量
        >>> HeroInfo.objects.bulk_create(
            objs=[
                HeroInfo(hname='红孩儿',hgender=0,hbook=book),
                HeroInfo(hname='铁扇公主',hgender=0,hbook=book)
            ],
            batch_size=3
        )
        [<HeroInfo: 红孩儿>, <HeroInfo: 铁扇公主>]
    • 2 - 查询

      • 2.1-基本查询

        • 查询规则:

          复制代码
          1. get 查询单一结果,如果不存在会抛出模型类 .DoesNotExist 异常,查询到多条数据会抛出MultipleObjectsReturned异常
          复制代码
          2. all 查询多个结果。
          复制代码
          3. count 查询结果数量。
          复制代码
          4. values 与 values_list 查询指定字段的所有值
        • 代码示例:

          python 复制代码
          >>> BookInfo.objects.all()
          <QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>, <BookInfo: 西游记>]>
          ​
          >>> book = BookInfo.objects.get(btitle='西游记')
          >>> book.id
          5
          ​
          >>> BookInfo.objects.all().values('btitle')
          >>> BookInfo.objects.all().values_list('btitle')
          >>> HeroInfo.objects.all().values('hbook_id').distinct()
          ​
          >>> BookInfo.objects.get(id=3)
          <BookInfo: 笑傲江湖>
          >>> BookInfo.objects.get(pk=3)
          <BookInfo: 笑傲江湖>
          ​
          >>> BookInfo.objects.get(id=100)
          """
          Traceback (most recent call last):
          File "<console>", line 1, in <module>
          File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
          return getattr(self.get_queryset(), name)(*args, **kwargs)
          File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/query.py", line 380, in get
          self.model._meta.object_name
          db.models.DoesNotExist: BookInfo matching query does not exist.
          """

          >>> BookInfo.objects.count()

      • 2.2-过滤查询

        • 查询规则

          复制代码
          1. filter 过滤出多个结果
          复制代码
          2. exclude 排除掉符合条件剩下的结果
          复制代码
          3. get 过滤单一结果
        • 过滤条件的使用语法

          复制代码
          # 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
          复制代码
          属性名称__比较运算符=值
        • 代码演练

          • 相等 exact:表示判等

            复制代码
            # 查询编号为1的图书。
            复制代码
            BookInfo.objects.filter(id__exact=1)
            复制代码
            # 可简写为:
            复制代码
            BookInfo.objects.filter(id=1)
          • 模糊查询

            • 使用语法

            • contains:是否包含(如果要包含 "%" 无需转义,直接写即可)

              复制代码
              startswith、endswith:以指定值开头或结尾。
              复制代码
              说明: 以下运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
            • 代码示例

              复制代码
              # 查询书名包含'传'的图书。
              复制代码
              BookInfo.objects.filter(btitle__contains='传')
              复制代码
              # 查询书名以'部'结尾的图书
              复制代码
              BookInfo.objects.filter(btitle__endswith='部')
          • 空查询 isnull:是否为null。

            复制代码
            # 查询书名不为空的图书
            复制代码
            BookInfo.objects.filter(btitle__isnull=False)
          • 范围查询 in:是否包含在范围内

          • 查询编号为1或3或5的图书

            复制代码
            BookInfo.objects.filter(id__in=[1, 3, 5])
          • 比较查询

            • 使用语法gt 大于 (greater then)

            • gte 大于等于 (greater then equ)

            复制代码
            lt 小于 (less then)
            复制代码
            lte 小于等于 (less then equal)
            复制代码
            exclude  不等于的运算符,使用exclude()过滤器
            • 代码示例

            • 查询编号大于3的图书

              BookInfo.objects.filter(id__gt=3)

              查询编号不等于3的图书

              BookInfo.objects.exclude(id=3)

          • 日期查询 year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。# 查询1980年发表的图书。BookInfo.objects.filter(bpub_date__year=1980)

            查询1990年1月1日后发表的图书。BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))

相关推荐
好吃的肘子23 分钟前
MongoDB 应用实战
大数据·开发语言·数据库·算法·mongodb·全文检索
小白学大数据26 分钟前
Scrapy框架下地图爬虫的进度监控与优化策略
开发语言·爬虫·python·scrapy·数据分析
浊酒南街26 分钟前
TensorFlow之微分求导
人工智能·python·tensorflow
weixin_4723394631 分钟前
MySQL MCP 使用案例
数据库·mysql
立秋678932 分钟前
用Python绘制梦幻星空
开发语言·python·pygame
alpszero44 分钟前
YOLO11解决方案之对象裁剪探索
人工智能·python·计算机视觉·yolo11
白云千载尽1 小时前
相机、雷达标定工具,以及雷达自动标定的思路
python·自动驾驶·ros
lqlj22331 小时前
Spark SQL 读取 CSV 文件,并将数据写入 MySQL 数据库
数据库·sql·spark
咕噜咕噜啦啦1 小时前
python爬虫实战训练
爬虫·python
盛夏绽放2 小时前
Python字符串常用内置函数详解
服务器·开发语言·python