如何使用 Django 的 ORM 截断表?

Posted

技术标签:

【中文标题】如何使用 Django 的 ORM 截断表?【英文标题】:How to TRUNCATE TABLE using Django's ORM? 【发布时间】:2011-02-28 15:51:33 【问题描述】:

要清空数据库表,我使用以下 SQL 查询:

TRUNCATE TABLE `books`

如何使用 Django 的模型和 ORM 截断表?

这个我试过了,还是不行:

Book.objects.truncate()

【问题讨论】:

虽然您在下面有几个很好的答案,但您应该意识到您的 sql 数据库中的表将在您模型中的表名前添加 appname_。 使用任何 SQL,而不仅仅是 TRUNCATE:***.com/questions/4532681/… 【参考方案1】:

使用 ORM 最接近的是 Book.objects.all().delete()

虽然有区别:截断可能会更快,但 ORM 也会追踪外键引用并删除其他表中的对象。

【讨论】:

谢谢。这可以解决问题。就我而言,速度并不重要。 这似乎不适用于每个数据库后端 - 当我在 sqlite3 上大约 3000 条记录的表上尝试上述操作时,我得到了 DatabaseError“太多 SQL 变量”。也许我只是缺少批处理/sqlite 的配置值。 @BernhardKircher:将我的添加视为单独的答案 mysql 中它也是 DELETE 而不是 TRUNCATE。没有使用 DELETE 重置索引。 Sqlite3 也是删除而不是截断。【参考方案2】:

您可以以一种快速且轻量级的方式完成此操作,但不使用 Django 的 ORM。您可以使用 Django 连接游标执行原始 SQL:

from django.db import connection
cursor = connection.cursor()
cursor.execute("TRUNCATE TABLE `books`")

【讨论】:

谢谢,但我更喜欢让我的应用程序与尽可能多的数据库引擎一起工作,而不是使用原始 sql TRUNCATE TABLE 是“典型”SQL 语法的一部分,尽管只是正式的 SQL:2008 的一部分。 Django 支持 Postgres、MySQL、SQLite* 和 Oracle。 postgresql.org/docs/8.1/interactive/sql-truncate.html dev.mysql.com/doc/refman/4.1/en/truncate-table.html download.oracle.com/docs/cd/B19306_01/server.102/b14200/… *SQLite 缺少 TRUNCATE [TABLE] 支持,您需要使用 DELETE FROM。当然,这仅在您需要性能时才适用。 截断也可能有问题(取决于使用的数据库系统)。例如。 Microsoft SQL Server 不允许截断外键引用的表。我只是想提一下,也许其他数据库系统有不同的行为。 在大多数数据库上,您需要在 execute() 调用之后调用 django.db.transaction.commit_unless_managed()。 小心,像 Oracle 和 MySQL 这样的许多 RDBMS 将 TRUNCATE 作为 DDL 处理,而不是 DML,它不是事务处理的一部分!【参考方案3】:

可以使用模型的_meta属性填写数据库表名:

from django.db import connection
cursor = connection.cursor()
cursor.execute('TRUNCATE TABLE "0"'.format(MyModel._meta.db_table))

重要提示:这不适用于继承模型,因为它们跨越多个表!

【讨论】:

【参考方案4】:

除了 Ned Batchelder 的回答和参考 Bernhard Kircher 的评论:

就我而言,我需要使用 webapp 清空一个非常大的数据库:

Book.objects.all().delete()

在开发SQLlite环境中,返回:

too many SQL variables

所以我添加了一些解决方法。它可能不是最整洁的,但至少在 truncate table 选项内置到 Django 的 ORM 之前它可以工作:

countdata = Book.objects.all().count()
logger.debug("Before deleting: %s data records" % countdata)
while countdata > 0:
    if countdata > 999:
        objects_to_keep = Book.objects.all()[999:]
        Book.objects.all().exclude(pk__in=objects_to_keep).delete()
        countdata = Book.objects.all().count()
    else:
        Book.objects.all().delete()
        countdata = Book.objects.all().count()

顺便说一句,我的一些代码是基于“Django Delete all but last five of queryset”的。

我在知道答案已经回答的情况下添加了此内容,但希望此添加内容对其他人有所帮助。

【讨论】:

不错,但在我的 MySQL 上:NotSupportedError: (1235, "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'") 那是什么版本? (mysql和django)谷歌搜索,我想出了mysql 5.0(对吗?)但是对于一个不再支持的非常旧的django版本..(code.djangoproject.com/ticket/10099)【参考方案5】:

我知道这是一个非常古老的问题,这里也很少有正确的答案,但我无法抗拒自己分享最优雅、最快的方式来解决这个问题。

class Book(models.Model):
    # Your Model Declaration

    @classmethod
    def truncate(cls):
        with connection.cursor() as cursor:
            cursor.execute('TRUNCATE TABLE  CASCADE'.format(cls._meta.db_table))

现在要截断 Book 表中的所有数据,只需调用

Book.truncate()

由于这是直接与您的数据库交互,它的执行速度会比这样做快得多

Book.objects.all().delete()

【讨论】:

【参考方案6】:

现在有一个库可以帮助您截断 Django 项目数据库中的特定表,它称为 django-truncate。

很简单,只需运行python manage.py truncate --apps myapp --models Model1,该表中的所有数据都会被删除!

在此处了解更多信息:https://github.com/KhaledElAnsari/django-truncate

【讨论】:

此管理命令似乎不会截断表。它的实现似乎正在调用_model.objects.all().delete(),这绝对不是截断。 github.com/KhaledElAnsari/django-truncate/blob/master/…【参考方案7】:

为了截断我的本地 sqllite 数据库,我最终得到了python manage.py flush

我最初尝试的是遍历模型并逐行删除所有内容:

models = [m for c in apps.get_app_configs() for m in c.get_models(include_auto_created=False)]

        for m in models:
            m.objects.all().delete()

但是因为我已经保护了外键,所以操作的成功取决于模型的顺序。

所以,我正在使用 te flush 命令截断我的本地测试数据库,它对我有用 https://docs.djangoproject.com/en/3.0/ref/django-admin/#django-admin-flush

【讨论】:

【参考方案8】:

这并没有直接回答 OP 的问题,但仍然是一个可以用来实现相同目标的解决方案 - 不同。


好吧,出于某种奇怪的原因(在此处尝试使用其他答案中建议的 RAW 方法时),我未能截断我的 Django 数据库缓存表,直到我做了这样的事情:

import commands
cmd = ['psql', DATABASE, 'postgres', '-c', '"TRUNCATE %s;"' % TABLE]
commands.getstatusoutput(' '.join(cmd))

基本上,我不得不求助于通过数据库的实用命令发出truncate 命令——在这种情况下是psql,因为我使用的是Postgres。因此,自动化命令行可能会处理这种极端情况。

可能会为别人节省一些时间......

【讨论】:

以上是关于如何使用 Django 的 ORM 截断表?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 django orm 将数据插入到多个表中

SqlAlchemy 用 ORM 截断表

如何创建临时表而不丢失 django 中的 ORM?

python postgresql orm 截断表

如何在 Django ORM 中为 M2M 关系表创建 UniqueConstraint?

如何从django orm中的多对多关系表中提取数据