我正在尝试在两个Django安装(生产和测试)之间同步数据。我在生产时使用./manage.py dumpdata --natural进行此操作,然后在测试时将./manage.py loaddata放入新的syncdb ed数据库中。

一切正常,直到我添加了新的自定义权限。生产syncdb以与空数据库上的新syncdb不同的顺序(具有不同的主键)加载了此新权限。因此,它将获得一个不同的ID。因此,尽管使用了自然键,但是当我尝试加载数据时,在加载第一个乱序权限对象时却遇到了此错误:

IntegrityError: duplicate key value violates unique constraint "auth_permission_content_type_id_codename_key"

我想解决此问题的最简单方法是从测试安装中的每个表中删除所有数据-也就是说,仅使用syncdb来创建表,而不是也加载初始数据。但是syncdb不允许您跳过初始数据/信号步骤。缺少显式枚举每个模型或表名的方法,调用syncdb后如何删除所有初始数据?还是有一种方法可以不使用syncdb而仅创建空表?
./manage.py flush不是我想要的-它重新加载初始数据并触发syncdb信号。

最佳答案

根据冲洗命令的帮助(我使用的是Django 1.3.1),执行的SQL与从./manage.py sqlflush获得的SQL相同,然后重新安装初始数据固定装置。

$ python manage.py help flush
Usage: manage.py flush [options]

Executes ``sqlflush`` on the current database.

要获得相同的数据擦除功能减去夹具加载,您可以通过调用./manage.py sqlflush获得SQL,然后使用Django内置的执行任意SQL的内置支持来执行该SQL:
from django.core.management import call_command, setup_environ
from your_django_project import settings
setup_environ(settings)

from django.db import connection
from StringIO import StringIO

def main():
    # 'call' manage.py flush and capture its outputted sql
    command_output = StringIO()
    call_command("sqlflush", stdout=command_output)

    command_output.seek(0)
    flush_sql = command_output.read()

    # execute the sql
    # from: https://docs.djangoproject.com/en/dev/topics/db/sql/#executing-custom-sql-directly
    cursor = connection.cursor()
    cursor.execute(flush_sql)

    print "db has been reset"

if __name__ == '__main__':
    main()

这样做还有一个好处,就是您可以在执行之前从./manage.py sqlflush修改SQL,以避免擦除您可能希望保持原样的表。

同样,根据the current Django docs,在Django 1.5中,新参数./manage.py flush --no-initial-data将重置数据,并且不加载初始数据夹具。

10-05 18:53
查看更多