目录
- ORM是什么
- ORM 的工作原理:
- ORM 的优点:
- 常见的 ORM 框架:
- 创建 Django ORM 模型类
- 要数据库中检查
- 常用字段类型
- 元选项 (Meta Options)
- 简化操作orm
- 常见的模型操作
- 模型操作
- 方法 2:
filter()
- 方法 3:
get()
- 方法 4:
exclude()
- 方法 5:
order_by()
- 方法 6:
values()
和values_list()
- 方法 7:
count()
- 方法 8:
first()
和last()
- 方法 9:
exists()
- 方法 10:
aggregate()
和annotate()
- 方法 11:
distinct()
- 方法 12:
select_related()
和prefetch_related()
ORM是什么
ORM(Object-Relational Mapping,对象关系映射)是一种用于简化数据库操作的技术。它通过将数据库中的表映射为编程语言中的对象,使开发者能够以面向对象的方式操作数据库,而不需要直接编写复杂的SQL语句。
ORM 的工作原理:
ORM 框架将数据库中的每一个表映射为程序中的一个类,表中的每一行映射为类的一个实例(对象),表中的每一列则映射为对象的一个属性。这样,开发者可以通过操作对象来对数据库进行增删改查等操作,而不需要手动编写 SQL 语句。
ORM 的优点:
- 简化数据库操作:使用 ORM 可以让开发者更专注于业务逻辑,而不必花费大量时间编写和调试 SQL 语句。
- 可维护性和可读性:ORM 提供了更抽象和面向对象的编程方式,代码通常更加简洁和易于维护。
- 跨数据库支持:ORM 框架通常能够支持不同的数据库,只需要更改配置文件即可实现数据库切换,而不需要改动代码。
- 安全性:ORM 能有效防止 SQL 注入等常见的数据库安全问题。
常见的 ORM 框架:
- Django ORM(Python):Django Web 框架自带的 ORM,用于与 MySQL、PostgreSQL、SQLite 等数据库交互。
- SQLAlchemy(Python):一个功能强大的 Python ORM 库,支持多种数据库。
- Hibernate(Java):一个广泛使用的 Java ORM 框架,通常与 Spring 框架一起使用。
- Entity Framework(C#):微软为 .NET 开发的 ORM 框架,用于和 SQL Server、MySQL 等数据库交互。
创建 Django ORM 模型类
在 Django 中,ORM 模型类用于将数据库中的表映射为 Python 对象,每个模型类对应数据库中的一张表,类的属性对应表中的字段。
在 Django 中,模型类需要继承 django.db.models.Model
类,并且模型类的每个属性代表 table
的一个字段。
示例模型类
假设我们有一个应用场景要记录用户信息,可以创建一个 User
模型类:
from django.db import models
class User(models.Model):
# 字段定义
name = models.CharField(max_length=100) # 字符串字段,对应数据库中的 VARCHAR
email = models.EmailField() # 邮箱字段,Django 提供的特殊类型
age = models.IntegerField() # 整数字段
created_at = models.DateTimeField(auto_now_add=True) # 自动设置为记录创建时间
# 可选方法,用于表示对象的字符串形式
def __str__(self):
return self.name
在 Django 中,可以通过运行迁移命令将 models.py
中定义的模型类转换为数据库中的表。这个过程分为两步:创建迁移文件 和 应用迁移到数据库。
步骤 1:创建迁移文件
迁移文件是 Django 用于记录模型变更的文件。你可以通过以下命令创建迁移文件:
在项目目录下执行创建迁移文件命令python manage.py makemigrations
PS E:\devops> python manage.py makemigrations
Migrations for 'myapp':
myapp\migrations\0001_initial.py
- Create model User
该命令会根据 models.py
中的模型定义,生成一组迁移文件,这些文件会记录模型的创建或更新。生成的迁移文件会存储在应用程序的 migrations
文件夹中。
步骤 2:应用迁移到数据库
创建完迁移文件后,接下来需要将这些迁移应用到数据库中。你可以通过以下命令执行迁移操作,将模型类转换为数据库中的表:
在项目目录下执行迁移到数据库命令python manage.py migrate
PS E:\devops> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, myapp, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying myapp.0001_initial... OK
Applying sessions.0001_initial... OK
这个命令会读取所有的迁移文件,并在数据库中创建对应的表结构。
步骤 3:查看迁移的数据库表结构
每个迁移前的 [X]
表示该迁移已经被应用到数据库,说明你的数据库架构已经与这些迁移保持同步
PS E:\devops> python manage.py showmigrations
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
[X] 0012_alter_user_first_name_max_length
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
myapp
[X] 0001_initial
sessions
[X] 0001_initial
常见问题
- 数据库配置:确保你已经正确配置了数据库连接信息,在项目的
settings.py
文件中,DATABASES
配置应包含你的数据库信息。例如:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 或者使用 'postgresql', 'sqlite3', 'oracle' 等
'NAME': 'your_db_name',
'USER': 'your_db_user',
'PASSWORD': 'your_db_password',
'HOST': 'localhost', # 例如,如果使用远程数据库,可以写上 IP
'PORT': '3306', # 对应的数据库端口
}
}
2.在应用中创建models.py:需要在settings.py
文件中进行设置
应用是否添加到INSTALLED_APPS
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', # 你的应用
]
3.修改模型后:如果你对模型进行了修改,例如增加字段或删除字段,需要重新执行:
python manage.py makemigrations
python manage.py migrate
python manage.py showmigrations
通过这些步骤,Django 会将 models.py
中的模型类自动转换为数据库中的表,简化数据库结构管理。
要数据库中检查
mysql> show create table myapp_user\G
*************************** 1. row ***************************
Table: myapp_user
Create Table: CREATE TABLE `myapp_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL,
`email` varchar(254) NOT NULL,
`age` int(11) NOT NULL,
`created_at` datetime(6) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
常用字段类型
Django 提供了丰富的字段类型来表示不同类型的数据。常用的字段类型有:
CharField
:用于存储短字符串,需指定max_length
参数,表示最大字符数。
name = models.CharField(max_length=100)
IntegerField
:用于存储整数类型。
age = models.IntegerField()
BooleanField
:存储布尔值(True
或False
)。
is_active = models.BooleanField(default=True)
EmailField
:用于存储电子邮件地址,会自动验证格式。
email = models.EmailField()
DateField
和DateTimeField
:用于存储日期和日期时间类型数据。
birthday = models.DateField()
created_at = models.DateTimeField(auto_now_add=True)
ForeignKey
:用于定义多对一的关系,表示当前模型和另一个模型之间的关系。
group = models.ForeignKey(Group, on_delete=models.CASCADE)
ManyToManyField
:用于定义多对多的关系。
tags = models.ManyToManyField(Tag)
TextField
:用于存储大段文本,类似于 SQL 的TEXT
类型。
description = models.TextField()
元选项 (Meta Options)
Django 模型类可以通过 Meta
内部类来配置一些额外的选项,例如指定数据库表名、排序等:
class User(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField()
class Meta:
# 指定表名
db_table = 'user_table'
# 默认排序方式
ordering = ['-created_at']
简化操作orm
一般地都是编写views.py文件去操作models.py中的模型类,通过前端url访问,这种方式太过繁琐,此时仅通过操作orm对象修改数据库表数据
- 启用Django shell,在项目根目录下
python manage.py shell
就可以像在views.py文件中一样,导入模型类操作orm对象
- ipython 结合 Django shell,同样在根目录下,结合ipython的自动补全,好处多多(推荐使用)
python manage.py shell -i ipython
- 直接登录到mysql,查询表信息,此时已直接进入settings.py文件指定的数据库中,可直接执行
sql
语句
python manage.py dbshell
常见的模型操作
- 创建对象并保存到数据库:
user = User(name="Alice", email="[email protected]", age=25)
user.save()
- 查询对象:
# 查询所有对象
users = User.objects.all()
# 根据条件查询对象
user = User.objects.get(id=1)
- 更新对象:
user = User.objects.get(id=1)
user.age = 30
user.save()
- 删除对象:
user = User.objects.get(id=1)
user.delete()
以下为在ipython中的操作
from myapp.models import models, User
user=User(name="Alice",email="[email protected]",age=25)
user.save()
users = User.objects.all()
print(users)
#<QuerySet [<User: Alice>]>
user.age=30
user.save()
user.delete()
#(1, {'myapp.User': 1})
对应数据库中的数据变化
mysql> select * from myapp_user;
+----+-------+-------------------+-----+----------------------------+
| id | name | email | age | created_at |
+----+-------+-------------------+-----+----------------------------+
| 1 | Alice | [email protected] | 25 | 2024-09-07 06:57:25.496603 |
+----+-------+-------------------+-----+----------------------------+
1 row in set (0.00 sec)
mysql> select * from myapp_user;
+----+-------+-------------------+-----+----------------------------+
| id | name | email | age | created_at |
+----+-------+-------------------+-----+----------------------------+
| 1 | Alice | [email protected] | 30 | 2024-09-07 06:57:25.496603 |
+----+-------+-------------------+-----+----------------------------+
1 row in set (0.00 sec)
mysql> select * from myapp_user;
Empty set (0.00 sec)
模型操作
新增数据
save()方法
最常见的方式是实例化一个模型对象,然后使用 .save() 方法将该对象保存到数据库。
# 1. 创建一个 User 对象
user = User(name="John Doe", email="[email protected]", age=25)
# 2. 保存对象到数据库
user.save()
create()方法
使用 create() 方法直接创建并保存数据
# 使用 create() 方法直接创建并保存数据
user = User.objects.create(name="Alice", email="[email protected]", age=30)
批量插入数据
bulk_create()
可以一次性插入多个对象,性能比逐个保存要更好
# 创建多个 User 对象的列表
users = [
User(name="Bob", email="[email protected]", age=22),
User(name="Charlie", email="[email protected]", age=28),
User(name="Daisy", email="[email protected]", age=35),
]
# 批量插入数据到数据库中
User.objects.bulk_create(users)
get_or_create方法
如果你希望在插入数据前先检查是否存在该条记录,可以使用 get_or_create() 方法。它会先尝试从数据库中查找匹配的对象,如果没有找到,则创建新对象并保存。
user, created = User.objects.get_or_create(
name="John Doe",
email="[email protected]",
defaults={'age': 25}
)
if created:
print("新用户已创建")
else:
print("用户已存在")
update_or_create方法
如果你希望先检查记录是否存在,如果存在则更新记录,否则创建新记录,可以使用 update_or_create() 方法
user, created = User.objects.update_or_create(
email="[email protected]",
defaults={'name': "John Doe", 'age': 26}
)
if created:
print("新用户已创建")
else:
print("用户信息已更新")
查询数据
方法 1:all()
all()
方法用于查询表中的所有记录。
# 查询所有用户
users = User.objects.all()
all()
返回的是一个 QuerySet
,即一组查询结果。
方法 2:filter()
filter()
方法用于根据条件过滤查询结果,返回所有匹配条件的对象。
# 查询年龄大于 25 的用户
users = User.objects.filter(age__gt=25)
# 查询名字为 "John Doe" 的用户
users = User.objects.filter(name="John Doe")
filter()
支持链式调用,可以组合多个条件。
方法 3:get()
get()
方法用于根据条件获取单个对象。如果查询的条件返回多个结果或没有结果,它会抛出异常。
# 查询 email 为 '[email protected]' 的用户
try:
user = User.objects.get(email="[email protected]")
except User.DoesNotExist:
print("用户不存在")
except User.MultipleObjectsReturned:
print("查询返回了多个用户")
get()
通常用于唯一性查询,确保条件返回的是单个结果。
方法 4:exclude()
exclude()
方法用于排除符合条件的记录,它的作用与 filter()
相反。
# 查询年龄不是 25 的用户
users = User.objects.exclude(age=25)
exclude()
返回不符合条件的对象集合。
方法 5:order_by()
order_by()
方法用于对查询结果进行排序。默认是升序,前面加上 -
表示降序。
# 按年龄升序排序
users = User.objects.order_by('age')
# 按创建时间降序排序
users = User.objects.order_by('-created_at')
方法 6:values()
和 values_list()
values()
方法用于返回指定字段的字典,而不是整个对象;values_list()
则返回一个包含字段值的元组。
# 只获取用户的名字和邮箱,返回字典
users = User.objects.values('name', 'email')
# 只获取用户的名字和邮箱,返回元组
users = User.objects.values_list('name', 'email')
方法 7:count()
count()
方法用于返回查询结果的数量。
# 查询年龄大于 25 的用户数量
count = User.objects.filter(age__gt=25).count()
方法 8:first()
和 last()
first()
和 last()
方法分别返回查询结果的第一个和最后一个对象。
# 获取第一个用户
first_user = User.objects.first()
# 获取最后一个用户
last_user = User.objects.last()
方法 9:exists()
exists()
方法用于检查是否有满足条件的对象,返回布尔值。
# 检查是否有年龄大于 25 的用户
user_exists = User.objects.filter(age__gt=25).exists()
方法 10:aggregate()
和 annotate()
aggregate()
方法用于执行聚合函数,如 COUNT
、SUM
、AVG
等;annotate()
则用于在查询结果中附加聚合数据。
from django.db.models import Count, Avg
# 计算所有用户的平均年龄
average_age = User.objects.aggregate(Avg('age'))
# 每个年龄有多少用户
age_count = User.objects.values('age').annotate(count=Count('id'))
方法 11:distinct()
distinct()
方法用于去除查询结果中的重复记录。
# 查询所有不同的用户年龄
distinct_ages = User.objects.values('age').distinct()
方法 12:select_related()
和 prefetch_related()
这些方法用于优化查询外键和多对多关系的字段,减少数据库查询次数。
# 假设 User 有一个外键 `group`,使用 select_related 进行外键的优化查询
users = User.objects.select_related('group').all()
# 假设 User 有一个多对多字段 `tags`,使用 prefetch_related 进行优化查询
users = User.objects.prefetch_related('tags').all()
修改数据
1.通过模型实例进行修改
修改数据最常见的方式是先查询出需要修改的对象,对其属性进行更改,然后调用 .save()
方法保存到数据库中。
# 1. 查询出需要修改的对象
user = User.objects.get(id=1)
# 2. 修改属性
user.name = "New Name"
user.age = 30
# 3. 保存修改
user.save()
说明:
- 查询对象:使用
get()
或filter()
查询需要修改的对象。 - 修改属性:通过直接赋值修改模型对象的属性值。
- 保存数据:调用
.save()
方法将修改保存到数据库中。Django 会自动生成UPDATE
语句
2.批量更新(update()
方法)
如果需要一次性修改多个对象的某个字段,可以使用 update()
方法。该方法会生成一个 UPDATE
SQL 语句,直接修改满足条件的所有对象。
# 批量修改年龄大于 25 岁的用户,将他们的年龄设置为 26
User.objects.filter(age__gt=25).update(age=26)
说明:
update()
方法会直接在数据库中执行,不会逐个加载对象到内存中,因此效率更高。- 该方法只适用于批量更新,并且只能更新对象的某些字段,无法调用
save()
来触发模型实例的额外逻辑(如save()
方法中的自定义逻辑)。
3.更新或创建(update_or_create()
方法)
如果你想实现“如果对象存在则更新,不存在则创建”的逻辑,update_or_create()
方法非常适合。
# 如果用户邮箱为 '[email protected]' 的记录存在,则更新名字;否则创建新用户
user, created = User.objects.update_or_create(
email='[email protected]',
defaults={'name': 'John Doe', 'age': 26}
)
if created:
print("新用户已创建")
else:
print("用户信息已更新")
说明:
update_or_create()
方法会先查询是否有符合条件的对象,如果存在,则更新它;如果不存在,则创建新的对象。
注意事项:
.save()
方法:当你通过实例进行修改时,必须手动调用.save()
方法才能将修改保存到数据库。update()
方法:该方法适用于批量修改操作,但它不会调用模型的save()
方法,也不会触发pre_save
或post_save
信号。- 事务控制:如果在修改数据时涉及多个步骤,建议使用 Django 的事务机制来确保数据一致性。
删除数据
1.删除单条数据
# 获取一条数据
record = User.objects.get(id=1)
# 删除这条数据
record.delete()
2.删除多条数据
你可以通过filter()
方法筛选出符合条件的多条数据,然后使用delete()
方法一次性删除它们。
# 筛选出满足条件的多条数据
records = User.objects.filter(status='inactive')
# 删除这些数据
records.delete()
注意:delete()
方法会直接从数据库中删除数据,删除后无法恢复,请谨慎操作。
3.批量删除
你可以通过filter()
方法筛选出符合条件的多条数据,然后使用delete()
方法一次性删除它们。
# 分批删除,避免大量数据删除时的性能问题
batch_size = 100
qs = User.objects.filter(status='inactive')
while qs.exists():
qs[:batch_size].delete()
注意:delete()
方法会直接从数据库中删除数据,删除后无法恢复,请谨慎操作。
4.使用事务删除数据
如果你希望在删除数据时使用事务,可以通过Django的transaction
模块来确保数据一致性。
from django.db import transaction
from myapp.models import User
# 使用事务确保一致性
with transaction.atomic():
User.objects.filter(status='inactive').delete()
标签:name,objects,数据库,django,orm,user,操作,方法,User
From: https://www.cnblogs.com/anyux/p/18402011