Skip to content

更新数据库中的数据

以下方法和函数允许更新数据库中的现有数据。

  • update(each: bool = False, **kwargs) -> int

  • update_or_create(**kwargs) -> Model

  • bulk_update(objects: List[Model], columns: List[str] = None) -> None

  • 模型

    • Model.update()方法
    • Model.upsert()方法
    • Model.save_lated() 方法
    • 查询集代理

    • QuerysetProxy.update_or_create(**kwargs) 方法

更新

update(each: bool = False, **kwargs) -> int

QuerySet级别更新用于一次更新具有相同值的多个记录。

您要么必须首先过滤 QuerySet,要么提供each=True 标志来更新整个表。

如果您不提供此标志或过滤器,则会引发 QueryDefinitionError。

返回更新的行数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Book(ormar.Model):
    ormar_config = ormar_base_config.copy(
        tablename="books",
    )

    id: int = ormar.Integer(primary_key=True)
    title: str = ormar.String(max_length=200)
    author: str = ormar.String(max_length=100)
    genre: str = ormar.String(
        max_length=100,
        default="Fiction",
    )


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    await Book.objects.create(
        title="Tom Sawyer", author="Twain, Mark", genre="Adventure"
    )
    await Book.objects.create(
        title="War and Peace", author="Tolstoy, Leo", genre="Fiction"
    )
    await Book.objects.create(
        title="Anna Karenina", author="Tolstoy, Leo", genre="Fiction"
    )

    await Book.objects.update(each=True, genre="Fiction")
    all_books = await Book.objects.filter(genre="Fiction").all()
    assert len(all_books) == 3


asyncio.run(run_query())

!!!警告 更新之前需要过滤查询集以防止意外覆盖。

1
To update whole database table `each=True` needs to be provided as a safety switch

更新或创建

update_or_create(**kwargs) -> Model

更新模型,或者在数据库中没有匹配项的情况下创建一个新模型。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import asyncio

import databases
import ormar
import sqlalchemy
from examples import create_drop_database

DATABASE_URL = "sqlite:///test.db"

ormar_base_config = ormar.OrmarConfig(
    database=databases.Database(DATABASE_URL),
    metadata=sqlalchemy.MetaData(),
)


class Book(ormar.Model):
    ormar_config = ormar_base_config.copy()

    id: int = ormar.Integer(primary_key=True)
    title: str = ormar.String(max_length=200)
    author: str = ormar.String(max_length=100)
    genre: str = ormar.String(
        max_length=100,
        default="Fiction",
    )


@create_drop_database(base_config=ormar_base_config)
async def run_query():
    await Book.objects.create(
        title="Tom Sawyer", author="Twain, Mark", genre="Adventure"
    )
    await Book.objects.create(
        title="War and Peace", author="Tolstoy, Leo", genre="Fiction"
    )
    await Book.objects.create(
        title="Anna Karenina", author="Tolstoy, Leo", genre="Fiction"
    )

    # if not exist the instance will be persisted in db
    vol2 = await Book.objects.update_or_create(
        title="Volume II", author="Anonymous", genre="Fiction"
    )
    assert await Book.objects.count() == 4

    # if pk or pkname passed in kwargs (like id here) the object will be updated
    assert await Book.objects.update_or_create(id=vol2.id, genre="Historic")
    assert await Book.objects.count() == 4


asyncio.run(run_query())

注意,如果你想创建一个新对象,你要么必须传递 pk 列值,要么 pk 列必须设置为自动增量

批量更新

bulk_update(objects: List["Model"], columns: List[str] = None) -> None

允许一次更新多个实例。

所有传递的模型都需要填充主键列。

您还可以通过将列列表作为字符串名称列表传递来选择要更新的字段。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# continuing the example from bulk_create
# update objects
for todo in todoes:
    todo.completed = False

# perform update of all objects at once
# objects need to have pk column set, otherwise exception is raised
await ToDo.objects.bulk_update(todoes)

completed = await ToDo.objects.filter(completed=False).all()
assert len(completed) == 3

模型方法

每个模型实例都有一组方法来保存、更新或加载自身。

###更新

您可以通过更新模型属性(字段)并调用 update() 方法来更新模型。

如果您尝试在没有设置主键的情况下更新模型,则会引发 ModelPersistenceError 异常。

!!!tip 阅读有关 models-update 中的 update() 方法的更多信息

更新插入

它是模型的 save() 或 update(**kwargs) 方法的代理。如果设置了 pk,则将调用 update() 方法。

!!!tip 阅读 models-upsert 中有关 upsert() 方法的更多信息

保存相关

方法会遍历调用该方法的模型的所有关系,并在每个未保存的模型上调用 upsert() 方法。

!!!tip 在 models-save-lated 中阅读有关 save_lated() 方法的更多信息

QuerysetProxy 方法

当直接访问相关的ManyToMany字段以及ReverseForeignKey时,返回相关模型的列表。

但同时它公开了 QuerySet API 的子集,因此您可以直接从父模型过滤、创建、选择相关模型等。

更新或创建

与上面的 update_or_create 函数完全相同,但允许您从关系的另一端更新或创建相关对象。

!!!tip 要了解有关 QuerysetProxy 的更多信息,请访问 querysetproxy 部分