Skip to content

Commit 0cdb6dc

Browse files
authored
1152 get_or_create raises ValueError (#1153)
* set `_ignore_missing=True` * populate data dict, instead of setting attributes afterwards * add a test * add name to test table
1 parent 2a637b8 commit 0cdb6dc

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

piccolo/query/methods/objects.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,20 @@ async def run(
6565
instance._was_created = False
6666
return instance
6767

68-
instance = self.table_class(_data=self.defaults)
68+
data = {**self.defaults}
6969

7070
# If it's a complex `where`, there can be several column values to
7171
# extract e.g. (Band.name == 'Pythonistas') & (Band.popularity == 1000)
7272
if isinstance(self.where, Where):
73-
setattr(
74-
instance,
75-
self.where.column._meta.name, # type: ignore
76-
self.where.value, # type: ignore
77-
)
73+
data[self.where.column] = self.where.value
7874
elif isinstance(self.where, And):
7975
for column, value in self.where.get_column_values().items():
8076
if len(column._meta.call_chain) == 0:
8177
# Make sure we only set the value if the column belongs
8278
# to this table.
83-
setattr(instance, column._meta.name, value)
79+
data[column] = value
80+
81+
instance = self.table_class(_data=data)
8482

8583
await instance.save().run(node=node, in_pool=in_pool)
8684

tests/table/test_objects.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from piccolo.columns.column_types import ForeignKey
2+
from piccolo.testing.test_case import AsyncTableTest
13
from tests.base import DBTestCase, engines_only, sqlite_only
24
from tests.example_apps.music.tables import Band, Manager
35

@@ -268,3 +270,32 @@ def test_prefetch_new_object(self):
268270
self.assertIsInstance(band.manager, Manager)
269271
self.assertEqual(band.name, "New Band 2")
270272
self.assertEqual(band.manager.name, "Guido")
273+
274+
275+
class BandNotNull(Band, tablename="band"):
276+
manager = ForeignKey(Manager, null=False)
277+
278+
279+
class TestGetOrCreateNotNull(AsyncTableTest):
280+
281+
tables = [BandNotNull, Manager]
282+
283+
async def test_not_null(self):
284+
"""
285+
There was a bug where `get_or_create` would fail for columns with
286+
`default=None` and `null=False`, even if the value for those columns
287+
was specified in the where clause.
288+
289+
https://github.com/piccolo-orm/piccolo/issues/1152
290+
291+
"""
292+
293+
manager = Manager({Manager.name: "Test"})
294+
await manager.save()
295+
296+
self.assertIsInstance(
297+
await BandNotNull.objects().get_or_create(
298+
BandNotNull.manager == manager
299+
),
300+
BandNotNull,
301+
)

0 commit comments

Comments
 (0)