From 6431151263fe125c4e07ea6f6360e6426741afc3 Mon Sep 17 00:00:00 2001 From: santa Date: Tue, 9 Feb 2016 19:18:14 +0100 Subject: [PATCH 1/4] Reset SQL sequences when new objects are imported --- import_export/resources.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/import_export/resources.py b/import_export/resources.py index bf910e946..490d33d9e 100644 --- a/import_export/resources.py +++ b/import_export/resources.py @@ -10,7 +10,8 @@ from django import VERSION from django.conf import settings -from django.db import transaction +from django.core.management.color import no_style +from django.db import connections, transaction, DEFAULT_DB_ALIAS from django.db.models.fields import FieldDoesNotExist from django.db.models.query import QuerySet from django.db.transaction import TransactionManagementError @@ -397,6 +398,16 @@ def import_data(self, dataset, dry_run=False, raise_errors=False, self._meta.report_skipped): result.rows.append(row_result) + # Reset the SQL sequences when new objects are imported + # Adapted from django's loaddata + if not dry_run and any(r.import_type == RowResult.IMPORT_TYPE_NEW for r in result.rows): + connection = connections[DEFAULT_DB_ALIAS] + sequence_sql = connection.ops.sequence_reset_sql(no_style(), [self.Meta.model]) + if sequence_sql: + with connection.cursor() as cursor: + for line in sequence_sql: + cursor.execute(line) + if use_transactions: if dry_run or result.has_errors(): savepoint_rollback(sp1) From c0d80879ad3d345cf2d02c8eac0ec9dfa381ce92 Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 11 Feb 2016 17:55:42 +0100 Subject: [PATCH 2/4] Add test. --- requirements/dev.txt | 1 + tests/core/tests/resources_tests.py | 23 ++++++++++++++++++++++- tests/settings.py | 12 ++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 605dfbd35..31abaa8f2 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,3 +1,4 @@ -r base.txt sphinx mysql-python +psycopg==2.6.1 diff --git a/tests/core/tests/resources_tests.py b/tests/core/tests/resources_tests.py index 628620b40..7103c2efe 100644 --- a/tests/core/tests/resources_tests.py +++ b/tests/core/tests/resources_tests.py @@ -4,9 +4,11 @@ from copy import deepcopy from datetime import date from decimal import Decimal -from unittest import skip +from unittest import skip, skipUnless +from django.conf import settings from django.contrib.auth.models import User +from django.db import IntegrityError from django.db.models import Count from django.db.models.fields import FieldDoesNotExist from django.test import TestCase, TransactionTestCase, skipUnlessDBFeature @@ -668,3 +670,22 @@ def test_create(self): BookResource = resources.modelresource_factory(Book) self.assertIn('id', BookResource.fields) self.assertEqual(BookResource._meta.model, Book) + + +@skipUnless( + 'postgresql' in settings.DATABASES['default']['ENGINE'], + 'Run only against Postgres') +class PostgresTests(TransactionTestCase): + # Make sure to start the sequences back at 1 + reset_sequences = True + + def test_create_object_after_importing_dataset_with_id(self): + dataset = tablib.Dataset(headers=['id', 'name']) + dataset.append([1, 'Some book']) + resource = BookResource() + result = resource.import_data(dataset) + self.assertFalse(result.has_errors()) + try: + Book.objects.create(name='Some other book') + except IntegrityError: + self.fail('IntegrityError was raised.') diff --git a/tests/settings.py b/tests/settings.py index 76aac5ebc..143efb5a0 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -56,6 +56,18 @@ } } } +elif os.environ.get('IMPORT_EXPORT_TEST_TYPE') == 'postgres': + IMPORT_EXPORT_USE_TRANSACTIONS = True + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'import_export', + 'USER': 'postgres', + 'PASSWORD': 'postgres', + 'HOST': 'localhost', + 'PORT': 5432 + } + } else: DATABASES = { 'default': { From 0e4fd4b7b5850c59bbca0ed9f9688554d6f82a9e Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 11 Feb 2016 18:51:35 +0100 Subject: [PATCH 3/4] Fix typo --- requirements/dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/dev.txt b/requirements/dev.txt index 31abaa8f2..33e073c21 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,4 +1,4 @@ -r base.txt sphinx mysql-python -psycopg==2.6.1 +psycopg2==2.6.1 From 8c3244e55b9952cfa7468b665dc823431c91f81e Mon Sep 17 00:00:00 2001 From: santa Date: Thu, 11 Feb 2016 19:13:06 +0100 Subject: [PATCH 4/4] Pass in PostgreSQL user and password via environment variables. --- tests/settings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/settings.py b/tests/settings.py index 143efb5a0..cb40a163d 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -62,8 +62,8 @@ 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'import_export', - 'USER': 'postgres', - 'PASSWORD': 'postgres', + 'USER': os.environ.get('IMPORT_EXPORT_POSTGRESQL_USER'), + 'PASSWORD': os.environ.get('IMPORT_EXPORT_POSTGRESQL_PASSWORD'), 'HOST': 'localhost', 'PORT': 5432 }