However, if the object to clone comes from a deferred queryset (after
calling `defer` or `only`), trying to save the copy raises some hard to
decipher exceptions.
{{{
class DeferCloneTest(TestCase):
@classmethod
def setUpTestData(cls):
SimpleItem.objects.create(name="test", value=42)
def _get_item(self):
item = SimpleItem.objects.defer('value').first() # same with
`only` instead of `defer`
item.pk = None
item._state.adding = True # doesn't seem to change anything
return item
def test_save(self):
self._get_item().save() # ValueError: Cannot force an update in
save() with no primary key.
def test_save_force_insert(self):
self._get_item().save(force_insert=True) #
SimpleItem.DoesNotExist
def test_bulk_create(self):
SimpleItem.objects.bulk_create([self._get_item()]) #
SimpleItem.DoesNotExist
}}}
Possibly related: #27419, #28019.
--
Ticket URL: <https://code.djangoproject.com/ticket/33312>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* cc: Egor R (added)
--
Ticket URL: <https://code.djangoproject.com/ticket/33312#comment:1>
* type: Bug => Cleanup/optimization
* stage: Unreviewed => Accepted
Comment:
Thanks for the report. Instances with deferred fields cannot be used for
copying model instances, because ''"When calling save() for instances with
deferred fields, only the loaded fields will be saved"'' (see
[https://docs.djangoproject.com/en/3.2/ref/models/querysets/#defer docs]).
It's niche and I don't think it's worth changing, or even if it's feasible
with backward compatibility, we can add a warning to the ''"Copying model
instances"'' section, e.g. `Instances with deferred fields cannot be used
....`.
--
Ticket URL: <https://code.djangoproject.com/ticket/33312#comment:2>
Comment (by Adam Sołtysik):
Ok, I understand that it might not make much sense to implement copying
instances with deferred fields. A warning in the docs would certainly be
helpful. Adding a more readable exception message (consistent for all the
cases) may also be worth considering, as sometimes it's not obvious that
our queryset has deferred fields, like when there's a custom manager
defined for a model. Especially the `DoesNotExist` exception in the last
two cases in very unclear.
--
Ticket URL: <https://code.djangoproject.com/ticket/33312#comment:3>
* owner: nobody => kdpisda
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/33312#comment:4>