Skip to content

Commit 190616f

Browse files
committed
fix #2: try inserting one by one if exception occurs in django
1 parent 4d12d43 commit 190616f

File tree

6 files changed

+117
-9
lines changed

6 files changed

+117
-9
lines changed

pyexcel_io/base.py

+9
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,12 @@ def from_query_sets(column_names, query_sets):
275275

276276
def is_empty_array(array):
277277
return len([x for x in array if x != '']) == 0
278+
279+
280+
def swap_empty_string_for_none(array):
281+
def swap(x):
282+
if x == '':
283+
return None
284+
else:
285+
return x
286+
return [swap(x) for x in array]

pyexcel_io/constants.py

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
MESSAGE_CANNOT_READ_FILE_TYPE_FORMATTER = "Cannot read content of file type %s from file %s"
2121
MESSAGE_LOADING_FORMATTER = "The plugin for file type %s is not installed. Please install %s"
2222
MESSAGE_EMPTY_ARRAY = "One empty row is found"
23+
MESSAGE_IGNORE_ROW = "One row is ignored"
24+
MESSAGE_DB_EXCEPTION = "Warning: Bulk insertion got below exception. Trying to do it one by one slowly."
2325

2426
FILE_FORMAT_CSV = 'csv'
2527
FILE_FORMAT_TSV = 'tsv'

pyexcel_io/djangobook.py

+22-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,19 @@
88
:license: New BSD License, see LICENSE for more details
99
"""
1010
from ._compact import OrderedDict
11-
from .constants import MESSAGE_EMPTY_ARRAY
11+
from .constants import (
12+
MESSAGE_EMPTY_ARRAY,
13+
MESSAGE_DB_EXCEPTION,
14+
MESSAGE_IGNORE_ROW
15+
)
1216
from .base import (
1317
BookReaderBase,
1418
SheetReaderBase,
1519
BookWriter,
1620
SheetWriter,
1721
from_query_sets,
18-
is_empty_array
22+
is_empty_array,
23+
swap_empty_string_for_none
1924
)
2025

2126

@@ -77,12 +82,25 @@ def write_row(self, array):
7782
if is_empty_array(array):
7883
print(MESSAGE_EMPTY_ARRAY)
7984
else:
85+
new_array = swap_empty_string_for_none(array)
8086
self.objs.append(self.mymodel(**dict(
81-
zip(self.column_names, self.initializer(array))
87+
zip(self.column_names, self.initializer(new_array))
8288
)))
8389

8490
def close(self):
85-
self.mymodel.objects.bulk_create(self.objs, batch_size=self.batch_size)
91+
try:
92+
self.mymodel.objects.bulk_create(self.objs, batch_size=self.batch_size)
93+
except Exception as e:
94+
print(MESSAGE_DB_EXCEPTION)
95+
print(e)
96+
for object in self.objs:
97+
try:
98+
object.save()
99+
except Exception as e2:
100+
print(MESSAGE_IGNORE_ROW)
101+
print(e2)
102+
print(object)
103+
continue
86104

87105

88106
class DjangoBookWriter(BookWriter):

pyexcel_io/sqlbook.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
BookWriter,
1919
SheetWriter,
2020
from_query_sets,
21-
is_empty_array
21+
is_empty_array,
22+
swap_empty_string_for_none
2223
)
2324

2425

@@ -78,7 +79,8 @@ def write_row(self, array):
7879
if is_empty_array(array):
7980
print(MESSAGE_EMPTY_ARRAY)
8081
else:
81-
self._write_row(array)
82+
new_array = swap_empty_string_for_none(array)
83+
self._write_row(new_array)
8284

8385
def _write_row(self, array):
8486
row = dict(zip(self.column_names, array))

tests/test_django_book.py

+61-2
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,46 @@
22
from pyexcel_io.djangobook import DjangoModelReader, DjangoModelWriter, DjangoBookReader, DjangoBookWriter
33

44

5+
class Package:
6+
def __init__(self, raiseException=False, **keywords):
7+
self.keywords = keywords
8+
self.raiseException = raiseException
9+
10+
def get_content(self):
11+
return self.keywords
12+
13+
def save(self):
14+
if self.raiseException:
15+
raise Exception("test exception")
16+
else:
17+
pass
18+
19+
520
class Attributable:
621
def __init__(self, adict):
722
self.mydict = adict
823

924
def __getattr__(self, field):
1025
return self.mydict[field]
1126

27+
1228
class Objects:
1329
def __init__(self):
1430
self.objs = []
1531

1632
def bulk_create(self, objs, batch_size):
17-
self.objs = objs
33+
self.objs = [ o.get_content() for o in objs ]
1834
self.batch_size = batch_size
1935

2036
def all(self):
2137
return [Attributable(o) for o in self.objs]
2238

39+
2340
class Field:
2441
def __init__(self, name):
2542
self.attname = name
2643

44+
2745
class Meta:
2846
def __init__(self):
2947
self.model_name = "test"
@@ -33,13 +51,54 @@ def update(self, data):
3351
for f in data:
3452
self.concrete_fields.append(Field(f))
3553

54+
3655
class FakeDjangoModel:
3756
def __init__(self):
3857
self.objects = Objects()
3958
self._meta = Meta()
4059

4160
def __call__(self, **keywords):
42-
return keywords
61+
return Package(**keywords)
62+
63+
64+
class ExceptionObjects(Objects):
65+
def bulk_create(self, objs, batch_size):
66+
raise Exception("faked exception")
67+
68+
69+
class FakeExceptionDjangoModel(FakeDjangoModel):
70+
def __init__(self, raiseException=False):
71+
self.objects = ExceptionObjects()
72+
self._meta = Meta()
73+
self.raiseException = raiseException
74+
75+
def __call__(self, **keywords):
76+
return Package(raiseExcpetion=self.raiseException,
77+
**keywords)
78+
79+
80+
class TestException:
81+
def setUp(self):
82+
self.data = [
83+
["X", "Y", "Z"],
84+
[1, 2, 3],
85+
[4, 5, 6]
86+
]
87+
self.result = [
88+
{'Y': 2, 'X': 1, 'Z': 3},
89+
{'Y': 5, 'X': 4, 'Z': 6}
90+
]
91+
92+
def test_sheet_save_to_django_model(self):
93+
model=FakeExceptionDjangoModel()
94+
writer = DjangoModelWriter([model, self.data[0], None, None])
95+
writer.write_array(self.data[1:])
96+
writer.close()
97+
# now raise excpetion
98+
model=FakeExceptionDjangoModel(raiseException=True)
99+
writer = DjangoModelWriter([model, self.data[0], None, None])
100+
writer.write_array(self.data[1:])
101+
writer.close()
43102

44103

45104
class TestSheet:

tests/test_sql_book.py

+19-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
class Pyexcel(Base):
2323
__tablename__='pyexcel'
2424
id=Column(Integer, primary_key=True)
25-
name=Column(String)
25+
name=Column(String, unique=True)
2626
weight=Column(Float)
2727
birth=Column(Date)
2828

@@ -138,6 +138,24 @@ def test_one_table_with_empty_rows(self):
138138
assert results == self.results
139139
mysession.close()
140140

141+
def test_one_table_with_empty_string_in_unique_field(self):
142+
mysession = Session()
143+
data = [
144+
['birth', 'id', 'name', 'weight'],
145+
[datetime.date(2014, 11, 11), 0, '', 11.25],
146+
[datetime.date(2014, 11, 12), 1, '', 12.25]
147+
]
148+
writer = SQLTableWriter(mysession,
149+
[Pyexcel,data[0], None, None])
150+
writer.write_array(data[1:])
151+
writer.close()
152+
query_sets=mysession.query(Pyexcel).all()
153+
results = from_query_sets(data[0], query_sets)
154+
assert results == [['birth', 'id', 'name', 'weight'],
155+
['2014-11-11', 0, None, 11.25],
156+
['2014-11-12', 1, None, 12.25]]
157+
mysession.close()
158+
141159
def test_one_table_using_mapdict_as_array(self):
142160
mysession = Session()
143161
self.data = [

0 commit comments

Comments
 (0)