为什么Django允许你重置postgres和其他DBMS上的序列(AutoID)字段而不是SQLite3?
查看sql_flush
中django/db/backends/sqlite3/base.py
方法的源代码,有一条评论说:
注意:不需要重置自动递增的索引(参见其他sql_flush()实现)。此时只返回SQL
我有一些测试,我加载了依赖于绝对主键id的fixture文件。因为Django没有为SQLite重置自动id字段,所以这些灯具无法正确加载。
在sqlite中重置自动ID列似乎有点微不足道:How can I reset a autoincrement sequence number in sqlite
答案 0 :(得分:0)
也许这段代码会有所帮助:
import os
from django.core.management import call_command
from django.db import connection
from django.utils.six import StringIO
def reset_sequences(app_name):
os.environ['DJANGO_COLORS'] = 'nocolor'
buf = StringIO()
call_command('sqlsequencereset', app_name, stdout=buf)
buf.seek(0)
sql = "".join(buf.readlines())
with connection.cursor() as cursor:
cursor.execute(sql)
print("Sequences for app '{}' reset".format(app_name))
答案 1 :(得分:0)
您可以按照以下步骤对sql_flush
进行猴子补丁以重置SQLite序列:
from django.db.backends.sqlite3.operations import DatabaseOperations
from django.db import connection
def _monkey_patch_sqlite_sql_flush_with_sequence_reset():
original_sql_flush = DatabaseOperations.sql_flush
def sql_flush_with_sequence_reset(self, style, tables, sequences, allow_cascade=False):
sql_statement_list = original_sql_flush(self, style, tables, sequences, allow_cascade)
if tables:
# DELETE FROM sqlite_sequence WHERE name IN ($tables)
sql = '%s %s %s %s %s %s (%s);' % (
style.SQL_KEYWORD('DELETE'),
style.SQL_KEYWORD('FROM'),
style.SQL_TABLE(self.quote_name('sqlite_sequence')),
style.SQL_KEYWORD('WHERE'),
style.SQL_FIELD(self.quote_name('name')),
style.SQL_KEYWORD('IN'),
', '.join(style.SQL_FIELD(f"'{table}'") for table in tables)
)
sql_statement_list.append(sql)
return sql_statement_list
DatabaseOperations.sql_flush = sql_flush_with_sequence_reset
您将在TransactionTestCase
中使用它,例如:
from django.test import TransactionTestCase
class TransactionTestCaseWithSQLiteSequenceReset(TransactionTestCase):
reset_sequences = True
@classmethod
def setUpClass(cls):
super().setUpClass()
if connection.vendor == 'sqlite':
_monkey_patch_sqlite_sql_flush_with_sequence_reset()
这确保了依赖固定主键的测试可以与SQLite和其他数据库后端(例如PostgreSQL)一起使用。但是,有关reset_sequences
的注意事项,请参见Django documentation。一方面,它会使测试变慢。