首页 > 其他分享 >django orm操作

django orm操作

时间:2024-09-07 18:47:51浏览次数:9  
标签:name objects 数据库 django orm user 操作 方法 User

目录

ORM是什么

ORM(Object-Relational Mapping,对象关系映射)是一种用于简化数据库操作的技术。它通过将数据库中的表映射为编程语言中的对象,使开发者能够以面向对象的方式操作数据库,而不需要直接编写复杂的SQL语句。

ORM 的工作原理:

ORM 框架将数据库中的每一个表映射为程序中的一个类,表中的每一行映射为类的一个实例(对象),表中的每一列则映射为对象的一个属性。这样,开发者可以通过操作对象来对数据库进行增删改查等操作,而不需要手动编写 SQL 语句。

ORM 的优点:

  1. 简化数据库操作:使用 ORM 可以让开发者更专注于业务逻辑,而不必花费大量时间编写和调试 SQL 语句。
  2. 可维护性和可读性:ORM 提供了更抽象和面向对象的编程方式,代码通常更加简洁和易于维护。
  3. 跨数据库支持:ORM 框架通常能够支持不同的数据库,只需要更改配置文件即可实现数据库切换,而不需要改动代码。
  4. 安全性: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

常见问题

  1. 数据库配置:确保你已经正确配置了数据库连接信息,在项目的 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 提供了丰富的字段类型来表示不同类型的数据。常用的字段类型有:

  1. CharField:用于存储短字符串,需指定 max_length 参数,表示最大字符数。
name = models.CharField(max_length=100)
  1. IntegerField:用于存储整数类型。
age = models.IntegerField()
  1. BooleanField:存储布尔值(TrueFalse)。
is_active = models.BooleanField(default=True)
  1. EmailField:用于存储电子邮件地址,会自动验证格式。
email = models.EmailField()
  1. DateFieldDateTimeField:用于存储日期和日期时间类型数据。
birthday = models.DateField()
created_at = models.DateTimeField(auto_now_add=True)
  1. ForeignKey:用于定义多对一的关系,表示当前模型和另一个模型之间的关系。
group = models.ForeignKey(Group, on_delete=models.CASCADE)
  1. ManyToManyField:用于定义多对多的关系。
tags = models.ManyToManyField(Tag)
  1. 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对象修改数据库表数据

  1. 启用Django shell,在项目根目录下
python manage.py shell

就可以像在views.py文件中一样,导入模型类操作orm对象

  1. ipython 结合 Django shell,同样在根目录下,结合ipython的自动补全,好处多多(推荐使用)
python manage.py shell -i ipython
  1. 直接登录到mysql,查询表信息,此时已直接进入settings.py文件指定的数据库中,可直接执行sql语句
python manage.py dbshell

常见的模型操作

  1. 创建对象并保存到数据库
user = User(name="Alice", email="[email protected]", age=25)
user.save()
  1. 查询对象
# 查询所有对象
users = User.objects.all()

# 根据条件查询对象
user = User.objects.get(id=1)
  1. 更新对象
user = User.objects.get(id=1)
user.age = 30
user.save()
  1. 删除对象
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() 方法用于执行聚合函数,如 COUNTSUMAVG 等;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()

这些方法用于优化查询外键和多对多关系的字段,减少数据库查询次数。

# 假设 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() 方法会先查询是否有符合条件的对象,如果存在,则更新它;如果不存在,则创建新的对象。
注意事项:
  1. .save() 方法:当你通过实例进行修改时,必须手动调用 .save() 方法才能将修改保存到数据库。
  2. update() 方法:该方法适用于批量修改操作,但它不会调用模型的 save() 方法,也不会触发 pre_savepost_save 信号。
  3. 事务控制:如果在修改数据时涉及多个步骤,建议使用 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

相关文章

  • web 开发(2)-Django
    MVCModel主要实现对数据库层面的访问,对数据库中的数据进行增删改查操作View,封装结果,生成展示html内容Controller,用于接受请求,处理业务逻辑,与Model和View实现交互,返回结果MVT流程Model主要实现对数据库层面的访问,对数据库中的数据进行增删改查操作View,相当于controlle......
  • g++如何判断>>是模板结束还是右移操作符
    intro在使用模板声明中,有一个经典的问题就是如何区分模板声明中的">>"是右移操作符还是一个模板声明的结束标志。好在新的C++标准削弱了这个很强的限制,而是允许reasonable的、根据上下文对符号进行不同的解析。C++11improvesthespecificationoftheparsersothatmultipl......
  • CF1991F Triangle Formation 题解
    Description你有\(n\)根棍子,从\(1\)到\(n\)编号。第\(i\)根棍子的长度是\(a_i\)。你需要回答\(q\)个问题。在每个查询中,你会得到两个整数\(l\)和\(r\)(\(1\lel<r\len,r−l+1\ge6\))。确定是否可以从编号为\(l\)到\(r\)的棒中选择\(6\)个不同的棒,形......
  • ArcMap批量附色操作,并保存mxd
    ArcMap批量附色操作,并保存mxd1、对单文件操作1、保存当前ArcMap中打开的shp文件为mxd文件打开label_shp_root中的任意一个shp文件夹保存成mxd文件2、对当前在arcmap中打开的shp文件应用color配色color配色是手动设置好一个shp文件夹的配色方案并保存成mxd文件应用color.......
  • 基于django+vue智能会议管理系统【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着企业规模的不断扩大和远程办公模式的兴起,会议管理成为了企业日常运营中不可或缺的一环。传统的手工或基于简单电子表格的会议管理方式......
  • 基于django+vue智能充电桩【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着新能源汽车产业的迅猛发展,电动汽车作为绿色出行的重要载体,其普及率日益提升。然而,电动汽车的广泛应用面临着一个关键挑战——充电基础......
  • 基于django+vue智慧阅读平台【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在信息爆炸的时代,阅读已成为获取知识、提升自我能力的重要途径。然而,面对海量的阅读资源和碎片化的信息环境,如何高效地选择与阅读成为了一......
  • 嵌入式Linux系统开发学习--Linux系统及其操作部分
    0.前言    由于毕业了工作原因,转行做嵌入式了,现在开始学习嵌入式Linux系统开发,后面也会学习单片机部分的知识,我也会陆续的将我的学习历程发送出来,迟迟不发文就是工作太忙了,现在进了家小企业,我负责的模块公司也没有人会,虽然是开源的,但是网上一堆牛鬼蛇神的资料,让我吃了......
  • Python毕业设计基于Django的动漫漫画手办周边商城
    文末获取资源,收藏关注不迷路文章目录一、项目介绍二、主要使用技术三、研究内容四、核心代码五、文章目录一、项目介绍动漫周边商城分为二个模块,分别是管理员功能模块和用户功能模块。管理员功能模块包括:文章资讯、文章类型、动漫活动、动漫商品功能,用户功能模块......
  • Linux网络操作的通用接口:Socket是怎么使用的?
    前言如果你在工作学习中经常见到socket相关的字眼,但总是未曾深究过其本质,相信这篇文章能够给你带来一些帮助。网络是计算机体系中绕不开的一环,而socket作为计算机网络体系的重要组成部分,也具备着相当重要的地位。但很多时候,虽然在书本或课堂上了解了TCP、IP等基础网络内容......