如何使用 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 截断表?的主要内容,如果未能解决你的问题,请参考以下文章