How do we enforce Django Admin to correctly call .update()
instead of .save()
to avoid triggering checks meant for object creation?
This is the models.py
:
class BinaryChoice():
# field definitions
...
def save(self, *args, **kwargs):
# check if binary
if self.question.qtype == 2:
if self.question.choices.count() < 2:
super(BinaryChoice, self).save(*args, **kwargs)
else:
raise Exception("Binary question type can contain at most two choices.")
else:
super(BinaryChoice, self).save(*args, **kwargs)
This passes the test, no surprises:
class SurveyTest(TestCase):
def test_binary_choice_create(self):
q1 = Question.objects.create(survey=survey, title='Have you got any internship experience?', qtype=Question.BINARY)
BinaryChoice.objects.create(question=q1, choice="Yes")
BinaryChoice.objects.create(question=q1, choice="No")
with self.assertRaises(Exception):
BinaryChoice.objects.create(question=q1, choice="Unsure / Rather not say")
The .save()
correctly checks that there isn't already 2 binary choices related to the same Question. However, in Django Admin, when using the interface to update the value (anything arbitrary, for example changing the value from "Yes" to "Sure") and saving it, one would expect the .update()
method to be called.
It turns out, according to Django docs and also a relevant thread here, the .save()
method is called instead. So now our update operation would fail when there's already 2 BinaryChoice
, even if you intend to update a value in-place using the Django Admin's default interface.
For completeness sake, this is admin.py
:
@admin.register(BinaryChoice)
class BinaryChoiceAdmin(admin.ModelAdmin):
pass