Ответ 1
Запустите sqlsequencereset, и он выведет все команды reset, которые вам нужны.
Недавно я импортировал большое количество данных из старой базы данных в новую базу данных Postgresql в качестве основы для моделей на новом сайте Django.
Я использовал идентификаторы из старой базы данных (поскольку строки в разных таблицах относятся друг к другу), но они не все последовательно - часто встречаются большие пробелы.
Я заметил, что когда я добавляю новый объект через приложение Django, он использует идентификаторы, начинающиеся с 1, что не было проблемой, поскольку не было строк с очень маленькими идентификаторами.
Но как только он достигает первой строки устаревших данных, postgres явно жалуется:
ERROR: duplicate key value violates unique constraint "django_comments_pkey"
DETAIL: Key (id)=(25) already exists.
Глядя на описания таблиц, я предполагаю, что мне нужно reset какую-то последовательность в каждой таблице:
Table "public.django_comments"
Column | Type | Modifiers
-----------------+--------------------------+--------------------------------------------------------------
id | integer | not null default nextval('django_comments_id_seq'::regclass)
...
Что мне нужно сделать для reset этой последовательности, чтобы новые строки были добавлены с идентификаторами, превышающими текущий максимальный ID?
Запустите sqlsequencereset, и он выведет все команды reset, которые вам нужны.
По предложению "Дмитрия Шевченко" вы можете запустить sqlsequencereset
, чтобы решить вашу проблему.
или
Вы можете выполнить SQL-запрос, сгенерированный sqlsequencereset
из Python, следующим образом (используя базу данных по умолчанию):
from django.core.management.color import no_style
from django.db import connection
from myapps.models import MyModel1, MyModel2
sequence_sql = connection.ops.sequence_reset_sql(no_style(), [MyModel1, MyModel2])
with connection.cursor() as cursor:
for sql in sequence_sql:
cursor.execute(sql)
Я тестировал этот код с помощью Python3.6, Django 2.0 и PostgreSQL 10.
Вот короткий фрагмент для сброса всех последовательностей в Django 1. 9+ (на основе http://djangosnippets.org/snippets/2774/) и совместимый с Python 3:
import os
from io import StringIO
os.environ['DJANGO_COLORS'] = 'nocolor'
from django.core.management import call_command
from django.apps import apps
from django.db import connection
commands = StringIO()
cursor = connection.cursor()
for app in apps.get_app_configs():
label = app.label
call_command('sqlsequencereset', label, stdout=commands)
cursor.execute(commands.getvalue())
Команда PostgreSQL:
ALTER SEQUENCE app_model_id_seq RESTART WITH 1
select setval('django_comments_id_seq', 12345);
Этот фрагмент Запустите sqlsequencereset во всех приложениях reset все идентификаторы всех пустых моделей
на основе @Paolo Melchiorre я создал собственную команду управления, которая заполняет все модели из выбранных приложений.
from django.core.management.base import BaseCommand
from django.apps import apps
from django.core.management.color import no_style
from django.db import connection
class Command(BaseCommand):
def handle(self, *args, **kwargs):
self.stdout.write('Reset AutoFields ...')
APPS = ['app1', 'app2']
APPS = [apps.get_app_config(app) for app in apps]
models = []
for app in APPS:
models.extend(list(app.get_models()))
sequence_sql = connection.ops.sequence_reset_sql(no_style(), models)
with connection.cursor() as cursor:
for sql in sequence_sql:
self.stdout.write(sql)
cursor.execute(sql)
self.stdout.write(self.style.SUCCESS('Reset AutoField complete.'))
протестировано с использованием python 3.7
и django 2.2
.