Python主流框架Django,ORM框架

 数据模型的增删改查

               一、 框架基本介绍

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

             ORMDjango框架中的使用 

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

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

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

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

                    2-安装并注册应用books

                    3-配置数据库连接信息

                            安装MySQL数据库驱动程序

    pip install PyMySQL

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

    from pymysql import install_as_MySQLdb
    ​
    install_as_MySQLdb()

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

    # 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'  # 数据库名字
        },
        
    }

                              

                            修改配置

    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创建数据库

    create database django_demo default charset=utf8;

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

    # 当前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作用 设置为特定值或者调用特定方法,如

  •   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 文件中定义模型类。

    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 manage.py makemigrations

  • 数据库迁移

    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 manage.py shell

  • 导入两个模型类,以便后续使用

    from books.models import BookInfo, HeroInfo

  • 查看MySQL数据库日志

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

    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语句
  • 代码示例

    >>> 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 查询指定字段的所有值
  • 代码示例:

    >>> 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))

  • 作者:D11_

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python主流框架Django,ORM框架

    发表回复