2010-01-18 2 views
6

У меня есть сценарий импорта, который запускает ряд команд, чтобы получать вещи из одной базы данных Postgres в другую, обе работают с той же кодовой базой Django. По большей части он использует ./manage.py loaddata для копирования, но некоторые объекты требуют дополнительной обработки, и я использую метод objects.create() Django в пользовательском скрипте для копирования данных. При этом, я указать идентификатор, то есть,Создание объекта Django и последовательности Postgres

MyObject.objects.create(id = 2, title = 'foo') 

После того, как скрипт будет сделано, я заметил, что ПОСЛЕДОВАТЕЛЬНОСТЬ Postgres неправильно на столах, где я сделал objects.create(). I., это было 50 до импорта, а еще 50 после, хотя в таблице теперь 150 объектов. Это, конечно, приводит к ошибкам при создании новых объектов, поскольку он пытается использовать уже существующий ID (во всех этих таблицах идентификатор является просто полем автоматического увеличения числа ванили). Однако таблицы, заполненные с помощью ./manage.py loaddata, выглядят нормально.

Я знаю, что я могу вручную сбросить эти таблицы с помощью ./manage.py sqlsequenreset Django. Но мне любопытно, почему последовательность, кажется, выходит из-под удара в первую очередь. Не увеличивает ли object.create() его? Я не замечаю ничего очевидного?

+0

нет лучших способов синхронизации базы данных? Вы проверяли структуру таблицы об автоматическом добавлении в поле id? – Prashanth

+2

Я не в курсе событий, связанных с postgres, но я предполагаю, что всякий раз, когда строка вставляется с «нулем» для столбца идентификации, она получает «заполняется» postgres (a la auto_increment) и последовательность увеличивается. Если вы укажете идентификатор самостоятельно, он обходит эту логику и просто вставляет строку напрямую. Я думаю, что django не пытается фактически увеличить порядковый номер, оставив его в базе данных. – shylent

+0

@shylent Я тоже летаю на интуиции, но, похоже, цель иметь переменную последовательности, увеличивающуюся в базе данных, - это не запускать max над идентификаторами для каждой записи на каждой вставке, когда идентификатор не указан , Чтобы сохранить последовательность в актуальном состоянии в случае использования OP, макс должен запускаться после каждой вставки, когда указан идентификатор. Я думаю, что оправданно требовать от пользователя вручную запросить обновление. –

ответ

12

все работает нормально. Конструкция django create() не имеет никакого отношения к последовательному вступлению непосредственно. Кратко:

  • PostgreSQL авто приращение («последовательного» типа) просто ярлык «создать последовательность + создать целое поля со значением последовательности, как по умолчанию»
  • Джанго AutoField первичного ключ (ID целого числа, если не указано иначе вами) только создает серийное поле
  • при указании идентификатора вручную, postgres вставляет это значение в базу данных . когда вы укажете значение, , он опускает параметр «по умолчанию», , который является правильным поведением.

поэтому, если вы хотите, чтобы ваши вставки увеличивали последовательность в соответствии с вашим выбором, вам необходимо вручную изменить значение последовательности, используя SELECT setval ('sequence_name', int_value); в противном случае оставьте его нулевым, и он будет автоматически увеличиваться - выберите текущий val и добавьте его +1 (если не указано иначе в определении последовательности).

Еще одна идея заключается в том, что вы создаете объект, а затем обновляете идентификатор (конечно, он не может быть уже использован), и в конце установите значение последовательности для максимального id.

+0

Спасибо мужчине, ты меня спасишь – peter

2

автоинкрементного поле работы, но года должны сделать запрос как

MyObject.objects.create(title='foo') 

без поля идентификатора, это autocalculated с базой данных.

+0

Я предполагаю, что мне интересно, что JSON, созданный собственной командой dumpdata Django, указывает на PK объектов, и команда loaddata, по-видимому, чтит те ПК без последовательности Postgre, которая запуталась. Итак, почему object.create не удается сделать это? Возможно, это просто недосмотр? – KRH

+0

@KRH Я думаю, что этот код в 'django/core/management/commands/load.py: 188' может объяснить нам этот вопрос. – diegueus9

+0

Получил это. Наверное, я несколько удивлен тем, что object.create() не делает этого, учитывая первичные ошибки, которые он может порождать, но я полагаю, что с точки зрения дизайна они считают, что проблема пользователей должна решаться. – KRH

Смежные вопросы