Django之ORM

news2024/10/7 14:29:16

一、Django模型层之ORM介绍

使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(增、删、改、查),而一旦谈到数据的管理操作,就需要用到数据库管理软件,例如mysql、oracle、Microsoft SQL Server等。

如果应用程序需要操作数据(比如将用户注册信息永久存放起来),那么我们需要在应用程序中编写原生sql语句,然后使用pymysql模块远程操作mysql数据

针对应用程序的数据操作,直接编写原生sql语句会存在两方面的问题,严重影响开发效率,如下

#1. sql语句的执行效率问题:应用开发程序员需要耗费一大部分精力去优化sql语句
#2. 数据库迁移问题:针对mysql开发的sql语句无法直接应用到oracle数据库上,一旦需要迁移数据库,便需要考虑跨平台问题

 为了解决上述问题,django引入了ORM的概念,ORM全称Object Relational Mapping,即对象关系映射,是在pymysq之上又进行了一层封装,对于数据的操作,我们无需再去编写原生sql,取代代之的是基于面向对象的思想去编写类、对象、调用相应的方法等,ORM会将其转换/映射成原生SQL然后交给pymysql执行

基于图2所示,有了ORM框架,开发人员既不用再去考虑原生SQL的优化问题,也不用考虑数据库迁移的问题,ORM都帮我们做了优化且支持多种数据库,这极大地提升了我们的开发效率

二、ORM的使用之模型

在django的ORM框架中,继承自django.db.models.Model的类称之为模型类,或简称模型。

一个模型是关于你的数据,唯一的、决定性的信息源、它包含存储数据的基本字段和方法。

通常,每个模型都映射到一个数据库表。模型中的属性对应数据库表的字段

如下所示:原生SQL与ORM的模型对应关系

三、ORM的使用之数据库迁移

1、创建模型

数据来源于数据库的表,而ORM的模型类对应数据库表,所以若我们想操作数据,必须先创建模型。

# 创建django项目,新建名为app01的app,在app01的models.py中创建模型
class Employee(models.Model):  # 必须是models.Model的子类
    id=models.AutoField(primary_key=True)

    name=models.CharField(max_length=16)

    gender=models.BooleanField(default=1)

    birth=models.DateField()

    department=models.CharField(max_length=30)

    salary=models.DecimalField(max_digits=10,decimal_places=1)

2、 配置settings.py

1.注册应用

但凡涉及到数据库同步操作的应用,都需要事先在settings.py的INSTALLED_APPS中完成注册

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    
    # django2.x+版本
    'app01.apps.App01Config', # 如果默认已经添加了,则无需重复添加
    # 'app02.apps.App02Config', # 若有新增的app,按照规律依次添加即可
    
    # django1.x版本
    'app01',  # 直接写应用名字
    # 'app02'
]

2.配置后端数据库

django的orm支持多种数据库(如PostgreSQL、MySQL、SQLite、Oracle等),如果想将上述模型转为mysql数据库中的表,需要settings.py中配置DATABASES,如下

# 删除\注释掉原来的DATABASES配置项,新增下述配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', # 使用mysql数据库
        'NAME': 'db1',          # 要连接的数据库
        'USER': 'root',         # 链接数据库的用于名
        'PASSWORD': '',         # 链接数据库的用于名                  
        'HOST': '127.0.0.1',    # mysql服务监听的ip  
        'PORT': 3306,           # mysql服务监听的端口  
        'ATOMIC_REQUEST': True, #设置为True代表同一个http请求所对应的所有sql都放在一个事务中执行 
                                #(要么所有都成功,要么所有都失败),这是全局性的配置,如果要对某个
                                #http请求放水(然后自定义事务),可以用non_atomic_requests修饰器 
        "AUTOCOMMIT":False, #全局取消自动提交,慎用
        'OPTIONS': {
            "init_command": "SET storage_engine=INNODB", #设置创建表的存储引擎为INNODB
            'isolation_level': "read committed",  # 默认为RC,可以设置成其他级别(详见下面解释)
        }
    }
}

"""
=================================》额外补充:
当运行并发负载时,来自不同会话的数据库事务(例如,处理不同请求的单独线程)可能会相互交互。 这些交互受每个会话的事务隔离级别的影响。 您可以在DATABASES中的数据库配置的OPTIONS部分中使用'isolation_level'条目设置连接的隔离级别。 此条目的有效值是四个标准隔离级别:

'read uncommitted'
'read committed'
'repeatable read'
'serializable'
或None来使用服务器配置的隔离级别。 
然而,Django最好使用read committed而不是MySQL的默认值repeatable read。 repeatable read可能导致数据丢失。
"""

强调!!!:在链接mysql数据库前,必须事先创建好数据库

mysql> create database db1; # 数据库名必须与settings.py中指定的名字对应上

3.配置日志

如果想打印orm转换过程中的sql,需要在settings中进行配置日志:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

首先执行下述命令来创建一个迁移

3、mysqlclient安装与兼容性问题

$ python manage.py makemigrations

会抛出异常

......
    raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?

提示我们需要事先安装好mysqlclient,并且默认加载的mysqlclient是模块MySQLdb,需要安装MySQL-python,但目前python官方第三库中最新版MySQLdb 1.2.5对python解释器以及MySQL Server的支持如下,并不支持python3.0+

• 对Python解释器的支持

– CPython : 支持2.4到2.7

– PyPy(用python实现的python解释器) : 支持到最新版本

• 对MySQL Server的支持

– 3.23=< MySQL <= 5.5

为此,有人在github中创建了一个MySQLdb1分支 来支持Cpython3.0+解释器,可以参照官网进行安装mysqlclient · PyPI

除了使用MySQLdb作为MySQLclient之外,我们还有可以使用pymysql

• Python解释器支持:

– CPython : 2.7 and >= 3.5

– PyPy : Latest version

• MySQL Server支持:

– MySQL >= 5.5

– MariaDB >= 5.5

比起前者,pymysql直接支持Cpython3.0+,安装简单

pip3 install pymysql

但是因为Django默认加载的MySQLclient是MySQLdb,所以需要作出修改

此时重新执行python manage.py makemigrations仍会抛出异常

......    
    File "/Users/liyang/PycharmProjects/egon_test/venv-3.8/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 37, in <module>
    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

需要根据上述异常提示的文件base.py路径打开文件,注释下述两行
 

if version < (1, 3, 13):
    raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)

如果重新执行makemigrations命令,扔抛出异常

......
    File “xxx\lib\site-packages\django\db\backends\mysql\operations.py”, line 146, in last_executed_query
query = query.decode(errors=‘replace’)
AttributeError: ‘str’ object has no attribute ‘decode’

需要根据上述异常提示的operations.py文件路径打开文件,把146行的decode修改为encode

ps:PyPI(Python Package Index)是Python官方的第三方库,所有人都可以下载或上传Python库到PyPI。可以访问PyPI · The Python Package Index,自行查看各个库的版本支持,

4、数据库迁移命令

最后在命令行中执行两条数据库迁移命令,即可在指定的数据库db1中创建表 :

$ python manage.py makemigrations
$ python manage.py migrate

# 注意:
# 1、makemigrations只是生成一个数据库迁移记录的文件,而migrate才是将更改真正提交到数据库执行
# 2、数据库迁移记录的文件存放于app01下的migrations文件夹里
# 3、了解:
如果要给迁移一个有意义的名称而不是生成的名称,则可以使用makemigrations --name选项:
python manage.py makemigrations --name xx app01 # 会在migrations目录下生成迁移文件0001_xx.py

python3 manage.py sqlmigrate app01 0001_xx  # 展示迁移的sql语句
python manage.py showmigrations # 项目的迁移及其状态。

注意:当我们直接去数据库里查看生成的表时,会发现数据库中的表与orm规定的并不一致,这完全是正常的,事实上,orm的字段约束就是不会全部体现在数据库的表中,比如我们为字段gender设置的默认值default=1,去数据库中查看会发现该字段的default部分为null

mysql> desc app01_employee; # 数据库中标签前会带有前缀app01_
+------------+---------------+------+-----+---------+----------------+
| Field      | Type          | Null | Key | Default | Extra          |
+------------+---------------+------+-----+---------+----------------+
| id         | int(11)       | NO   | PRI | NULL    | auto_increment |
| name       | varchar(16)   | NO   |     | NULL    |                |
| gender     | tinyint(1)    | NO   |     | NULL    |                |
| birth      | date          | NO   |     | NULL    |                |
| department | varchar(30)   | NO   |     | NULL    |                |
| salary     | decimal(10,1) | NO   |     | NULL    |                |
+------------+---------------+------+-----+---------+----------------+

,虽然数据库没有增加默认值,但是我们在使用orm插入值时,完全为gender字段插入空,orm会按照自己的约束将空转换成默认值后,再提交给数据库执行

5、模型字段的增、删、改

在表生成之后,如果需要增加、删除、修改表中字段,需要这么做

# 一:增加字段
#1.1、在模型类Employee里直接新增字段,强调:对于orm来说,新增的字段必须用default指定默认值
publish = models.CharField(max_length=12,default='人民出版社',null=True)
#1.2、重新执行那两条数据库迁移命令


# 二:删除字段
#2.1 直接注释掉字段
#2.2 重新执行那两条数据库迁移命令

# 三:修改字段
#2.1 将模型类中字段修改
#2.2 重新执行那两条数据库迁移命令

6、加载django配置

在开发django项目时,如果我们想跳过django的启动与操作流程,只测试某一部分的代码的功能,需要首先引入django的配置环境才可以

在任意路径下新建一个py文件(文件名任意),内容如下

import sys
import os
import django

# 1、将项目的根目录填入环境变量
BASE_DIR = os.path.dirname(传入项目所在的根目录)
sys.path.append(BASE_DIR)

# 2、引入项目的配置环境,然后无需启动django项目就可以使用其配置环境了
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名.settings')
django.setup()

# 可以将上述代码粘贴进交互式环境,直接在交互式环境测试

if __name__ == "__main__":
	# 编写测试代码,直接运行本文件即可
    from app01.models import Employee

    all = Employee.objects.all().values()
    print(all)

四、基本使用简介

增加一条记录

obj=Employee(name="ly",gender=0,birth='1997-01-27',department="财务部",salary=100.1)
obj.save()

查询记录

obj = Employee.objects.filter(name="ly").first()  # 查询所有名字为ly的记录并取第一条
print(obj.id, obj.name, obj.birth)  # 输出1 Egon 1997-01-27

 修改记录

Employee.objects.filter(name="ly").update(name="LY") # 过滤出所有名字为ly的记录并将name字段改成大写LY

删除记录

Employee.objects.filter(name="LY").delete() # 过滤出所有名字为LY的记录并删除

五、orm简单示例

定一个Person模型,有两个属性first_name与last_name

from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

first_name与last_name是这个模型的字段,每个字段都被指定为类属性,每个属性都映射到数据库列。

上面的Person模型将创建如下一个数据库表

CREATE TABLE myapp_person (
    "id" serial NOT NULL PRIMARY KEY,
    "first_name" varchar(30) NOT NULL,
    "last_name" varchar(30) NOT NULL
);

一些注意事项:

1、数据库中生成的表会加上"app名_"作为前缀,如myapp_persion,也可以重新为别的名称,详见第四节 2、会自动添加一个id字段作为主键字段,但也可以重写此行为,详见第3.3小节 3、本例中的CREATE TABLE SQL是使用PostgreSQL语法格式化的,但值得注意的是Django使用的SQL是根据设置文件中指定的数据库后端定制

六、使用模型



一旦你定义了模型,你就需要告诉djano你将要使用这些模型。如何做到呢? 需要通过编辑配置文件settings.py,在配置项INSTALLED_APPS注册你包含模型文件 models.py所在的app

例如,如果你的app的模型在myapp.models里,INSTALLED_APPS配置如下

INSTALLED_APPS = [
    #...
    'myapp',
    #...
]

然后运行命令

python manage.py makemigrations
python manage.py migrate


Django 提供了基于 web 的管理工具用来管理我们的模型。如何使用呢

• 1、通常我们在生成项目时就会在 urls.py 中自动设置好,如下

urlpatterns = [
    path('admin/', admin.site.urls),
]

• 2、启动Django ,管理工具就可以运行了,在浏览器中访问 http://127.0.0.1:8000/admin/,得到如下界面:

• 3、你可以通过命令 python manage.py createsuperuser 来创建超级用户,如下所示:

# python manage.py createsuperuser
Username (leave blank to use 'root'): egon
Email address: admin@runoob.com
Password:
Password (again):
Superuser created successfully.

之后输入用户名密码登录,界面如下:

• 4、为了让 admin 界面管理某个数据模型,我们需要先注册该数据模型到 admin。比如,我们之前在 app01/models.py中已经创建了模型 Person 。修改 app01/admin.py:

from django.contrib import admin

# Register your models here.

from app01.models import Person
admin.site.register(Person)

刷新页面即可看到Person数据表,可以在模型类中新增str方法来控制记录的显示内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/692189.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

护航行业安全!安全狗入选2023年度中国数字安全能力图谱(行业版)

近日&#xff0c;数世咨询正式发布了《2023年度中国数字安全能力图谱&#xff08;行业版&#xff09;》。 作为国内云原生安全领导厂商&#xff0c;安全狗也入选多个细项。 厦门服云信息科技有限公司&#xff08;品牌名&#xff1a;安全狗&#xff09;成立于2013年&#xff0c;…

8大service mesh框架大比拼,Istio不是唯一的选择!

文章目录 一、IsitoConsulLinkerdKumaOpen Service MeshMesheryTraefik MeshService Mesh Interface&#xff08;SMI&#xff09; 公众号&#xff1a; MCNU云原生&#xff0c;文章首发地&#xff0c;欢迎微信搜索关注&#xff0c;更多干货&#xff0c;第一时间掌握&#xff01…

Linux bluez蓝牙开发的准备工作

最近为了搞这个蓝牙的事情&#xff0c;忙碌了好几天&#xff0c;我就是想结合 bluez 的代码随便玩一下蓝牙设备&#xff0c;而且能够参考源码写点测试程序来操作这个蓝牙设备。这里只是说明 Linux 下的准备工作而非嵌入式的arm。 1&#xff0c;系统支持 我用的是真机安装的 D…

路由与交换技术(H3C)①——计算机网络基础

系列文章目录 ①——计算机网络基础 路由与交换技术&#xff08;H3C&#xff09;①——计算机网络概述 系列文章目录一 计算机网络概述1.1 计算机网络1.2 计算机网络的基本功能1.2.1 资源共享1.2.2 分布式处理与负载均衡1.2.3 综合信息服务 二 计算机网络的演进2.1 主机互联时…

Unity Editor扩展 实现一个Excel读表窗口

设计 Unity Editor窗口类 public class ExcelEditorWindow : EditorWindow {[MenuItem( "Frameworks/读表配置界面", false, 10 )]private static void Open(){Rect wr new Rect( 0, 0, 500, 500 );ExcelEditorWindow window ( ExcelEditorWindow ) EditorWindow.…

津津乐道设计模式 - 组合模式详解(以餐厅菜单系统举例让你快速掌握)

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

基于Python所写的玛丽冒险设计

点击以下链接获取源码资源&#xff1a; https://download.csdn.net/download/qq_64505944/87953199 《玛丽冒险》程序使用说明 在PyCharm中运行《玛丽冒险》即可进入如图1所示的游戏主界面。 图1 游戏主界面 具体的操作步骤如下&#xff1a; &#xff08;1&#xff09;游戏…

数据库监控与调优【十四】—— COUNT语句优化

COUNT语句优化 有关COUNT的几个实验与结论 准备工作 create table user_test_count (id int primary key not null auto_increment,name varchar(45),age int,email varchar(60),birthday date ) engine innodb;insert into user_test_count (id, name, a…

算法设计与分析之回溯法

文章目录 1. 回溯法简介1.1 DFS的基本思想1.2 回溯法的基本思想1.3 回溯法和DFS的区别1.4 剪枝 2. 01背包问题&#xff1a;子集树2.1 问题介绍2.2 解决思路2.3 算法实现2.4 如何优化 3. 旅行商问题TSP&#xff1a;排序树3.1 问题介绍3.2 解决思路3.3 算法框架3.4 算法实现 4. 总…

项目一点点记录

kafka发布通知 kafka是消息队列&#xff0c;kafka采用发布订阅模式进行消息的生产与消费。在项目中&#xff0c;我们采用spring来整合kafka&#xff0c; 通过定义事件event来封装 点赞、关注、评论三类事件&#xff0c;event实体中有 事件主题topic&#xff0c;当前用户id&…

怎么给PDF添加图片水印?其实很简单,看这篇就会了!

许多人都意识到版权问题的重要性&#xff0c;尽管在日常生活中我们可能很少遇到&#xff0c;但在办公和学习中却经常涉及到此类问题。例如&#xff0c;我们辛辛苦苦制作的PDF文件&#xff0c;如何确保不被他人盗用呢?这就涉及到如何为PDF添加图片水印的问题&#xff0c;相当于…

无向图G的广度优先搜索和深度优先搜索以及完整程序

图的遍历算法有两种&#xff1a;广度优先搜索和深度优先搜索 一.广度优先搜索类似于层次遍历&#xff0c;需要借助辅助队列 空间复杂度为O(|V|);空间复杂度由辅助队列大小决定 时间复杂度为O(|V||E|) 为避免同一顶点被多次访问&#xff0c;设计visited[]来标记顶点 二.深度…

MyBatis 从初识到掌握

目录 今日良言&#xff1a;与其抱怨于黑暗&#xff0c;不如提灯向前行 一、初识MyBatis 1.MyBatis定义 2.为什么要学习MyBatis 3.MyBatis的创建 二、MyBatis的相关操作 1.增删改查操作 2.动态SQL使用 今日良言&#xff1a;与其抱怨于黑暗&#xff0c;不如提灯向前行 一…

UE4/5 通过Control rig的FullBody【蜘蛛模型,不用basic ik】

目录 根设置 FullBody IK 额外骨设置 ​编辑 晃动效果 根设置 第一步你需要准备一个蜘蛛模型&#xff0c;不论是官方示例或者是epic上购买的模型 然后我用的是epic上面购买的一个眼球蜘蛛&#xff1a; 第一步&#xff0c;我们从根创建一个空项【这个记得脱离父子级到root之…

SQLServer 2016 R2数据库新建、附加、分离、备份、还原、复制等基本操作

一、打开Microsoft SQL Server Management Studio 在桌面上找到图标&#xff0c;双击运行 打开Microsoft SQL Server Management Studio 17 输入服务器名称&#xff0c;选择SQL Server 身份验证&#xff0c;sa和sa密码&#xff0c;可以勾选记住密码&#xff0c;以便以后的登录…

分享基于安卓项目的单元测试总结

前言&#xff1a; 负责公司的单元测试体系的搭建&#xff0c;大约有一两个月的时间了&#xff0c;从最初的框架的调研&#xff0c;到中期全员的培训&#xff0c;以及后期对几十个项目单元测试的引入和推进&#xff0c;也算是对安卓的单元测试有了一些初步的收获以及一些新的认…

【雕爷学编程】Arduino动手做(131)---跑马灯矩阵键盘模块

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

线性代数基础--矩阵

矩阵 矩阵是由排列在矩形阵列中的数字或其他数学对象组成的表格结构。它由行和列组成&#xff0c;并且在数学和应用领域中广泛使用。 基本概念 元素&#xff1a;矩阵中的每个数字称为元素。元素可以是实数、复数或其他数学对象。 维度&#xff1a;矩阵的维度表示矩阵的行数和…

vtk创建点

使用vtk库创建三维空间中的点 引言开发环境示例一项目结构实现代码 运行效果示例二项目结构实现代码 运行效果总结 引言 本文仅适合初学者。 本文不提供vtk动态库的生成&#xff0c;以及在QtCreator中的引进vtk时的配置。 本文先由示例一开始&#xff0c;然后再在示例一的基础…

aws使用外部 ID对其他账号授权

点击前往授权,进入控制台 https://signin.aws.amazon.com/signin?redirect_urihttps%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3FhashArgs%3D%2523%26isauthcode%3Dtrue%26state%3DhashArgsFromTB_eu-north-1_f2d9c316b93c0026&client_idarn%3Aaws%3Asignin%3A%…