Skip to content

Commit 3efcfb6

Browse files
committed
Fix 'pk' not being a valid conflict target
Fixes #23
1 parent 59233d7 commit 3efcfb6

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

psqlextra/compiler.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@ def _get_model_field(self, name: str):
215215

216216
field_name = self._normalize_field_name(name)
217217

218+
# 'pk' has special meaning and always refers to the primary
219+
# key of a model, we have to respect this de-facto standard behaviour
220+
if field_name == 'pk' and self.query.model._meta.pk:
221+
return self.query.model._meta.pk
218222
for field in self.query.model._meta.local_concrete_fields:
219223
if field.name == field_name or field.column == field_name:
220224
return field

tests/test_on_conflict.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,29 @@ def test_on_conflict_unique_together_fk(conflict_action):
304304
)
305305

306306
assert id3 == id4
307+
308+
309+
@pytest.mark.parametrize("conflict_action", CONFLICT_ACTIONS)
310+
def test_on_conflict_pk_conflict_target(conflict_action):
311+
"""Tests whether `on_conflict` properly accepts
312+
the 'pk' as a conflict target, which should resolve
313+
into the primary key of a model."""
314+
315+
model = get_fake_model({
316+
'name': models.CharField(max_length=255)
317+
})
318+
319+
obj1 = (
320+
model.objects
321+
.on_conflict(['pk'], conflict_action)
322+
.insert_and_get(pk=0, name='beer')
323+
)
324+
325+
obj2 = (
326+
model.objects
327+
.on_conflict(['pk'], conflict_action)
328+
.insert_and_get(pk=0, name='beer')
329+
)
330+
331+
assert obj1.name == 'beer'
332+
assert obj2.name == 'beer'

0 commit comments

Comments
 (0)