python 如何使用Django的ORM截断表?

p8ekf7hl  于 2023-02-02  发布在  Python
关注(0)|答案(9)|浏览(221)

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

TRUNCATE TABLE `books`

如何使用Django的模型和ORM截断一个表?
我试过了,但没用:

Book.objects.truncate()
mzaanser

mzaanser1#

与ORM最接近的是Book.objects.all().delete()
但也有不同之处:truncate可能会更快,但ORM也会追踪外键引用并删除其他表中的对象。

a9wyjsp7

a9wyjsp72#

你可以用一种快速而轻量级的方式来完成,但不要使用Django的ORM。你可以使用Django连接游标来执行原始SQL:

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

ffx8fchx3#

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

from django.db import connection
cursor = connection.cursor()
cursor.execute('TRUNCATE TABLE "{0}"'.format(MyModel._meta.db_table))
    • 重要信息**:这不适用于继承的模型,因为它们跨越多个表!
camsedfj

camsedfj4#

除了内德·巴彻尔德的回答和伯恩哈德·基彻的评论外:
在我的例子中,我需要使用webapp清空一个非常大的数据库:

Book.objects.all().delete()

在SQLlite开发环境中,它返回:

too many SQL variables

所以我添加了一个小的变通方法,它可能不是最简洁的,但至少在Django的ORM中内置truncate table选项之前是有效的:

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“的。
我添加了这个,同时意识到答案已经回答了,但希望这个添加将帮助其他一些人。

j2qf4p5b

j2qf4p5b5#

我知道这是一个很老的问题,很少有正确的答案是在这里,但我不能抗拒自己分享最优雅和最快的方式来服务于这个问题的目的.

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()
c7rzv4ha

c7rzv4ha6#

现在有一个库可以帮助您截断Django项目数据库中的特定TABLE,它叫做django-truncate
很简单,只需运行python manage.py truncate --apps myapp --models Model1,该表中的所有数据都将被删除!
在此了解更多信息:https://github.com/KhaledElAnsari/django-truncate

m528fe3b

m528fe3b7#

对于我来说,要截断我的本地sqlite数据库,我最终使用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

cu6pst1q

cu6pst1q8#

  • 此代码使用PosgreSQL方言。省略级联位以使用标准SQL。*

根据Shubho Shaha的回答,您还可以为此创建一个模型管理器。

class TruncateManager(models.Manager):
    def truncate(self, cascade=False):
        appendix = " CASCADE;" if cascade else ";"
        raw_sql = f"TRUNCATE TABLE {self.model._meta.db_table}{appendix}"
        cursor = connection.cursor()
        cursor.execute(raw_sql)

class Truncatable(models.Model):
    class Meta:
        abstract = True

    objects = TruncateManager()

然后,您可以扩展Truncatable以创建可截断对象:

class Book(Truncatable):
    ...

这将允许您在所有从Truncatable扩展的模型上调用truncate。

Book.objects.truncate()

我还添加了一个使用级联的标志,该标志(危险区域)还将:“自动截断外键引用任何指定表或由于CASCADE而添加到组中的任何表的所有表。",这显然更具破坏性,但将允许代码在原子事务内运行。

jbose2ul

jbose2ul9#

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

嗯,由于一些奇怪的原因(在尝试使用其他答案中建议的RAW方法时),我未能截断Django数据库缓存表,直到我执行了如下操作:

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

基本上,我不得不通过数据库的实用程序命令发出truncate命令-在本例中是psql,因为我使用的是Postgres。
可能会帮别人省点时间...

相关问题