1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

[1.8.x] Fixed #23617 -- Added get_pk_value_on_save()

The method is mainly intended for use with UUIDField. For UUIDField we
want to call the field's default even when primary key value is
explicitly set to None to match the behavior of AutoField.

Thanks to Marc Tamlyn and Tim Graham for review.

Backport of 8adc59038c from master
This commit is contained in:
Anssi Kääriäinen
2015-01-28 13:40:48 +02:00
committed by Tim Graham
parent 9ffe013caa
commit 43b0131fb5
6 changed files with 50 additions and 0 deletions

View File

@@ -772,6 +772,9 @@ class Model(six.with_metaclass(ModelBase)):
if f.name in update_fields or f.attname in update_fields]
pk_val = self._get_pk_val(meta)
if pk_val is None:
pk_val = meta.pk.get_pk_value_on_save(self)
setattr(self, meta.pk.attname, pk_val)
pk_set = pk_val is not None
if not pk_set and (force_update or update_fields):
raise ValueError("Cannot force an update in save() with no primary key.")

View File

@@ -506,6 +506,17 @@ class Field(RegisterLookupMixin):
return _load_field, (self.model._meta.app_label, self.model._meta.object_name,
self.name)
def get_pk_value_on_save(self, instance):
"""
Hook to generate new PK values on save. This method is called when
saving instances with no primary key value set. If this method returns
something else than None, then the returned value is used when saving
the new instance.
"""
if self.default:
return self.get_default()
return None
def to_python(self, value):
"""
Converts the input value into the expected Python data type, raising

View File

@@ -345,6 +345,11 @@ class QuerySet(object):
obj.save(force_insert=True, using=self.db)
return obj
def _populate_pk_values(self, objs):
for obj in objs:
if obj.pk is None:
obj.pk = obj._meta.pk.get_pk_value_on_save(obj)
def bulk_create(self, objs, batch_size=None):
"""
Inserts each of the instances into the database. This does *not* call
@@ -369,6 +374,8 @@ class QuerySet(object):
self._for_write = True
connection = connections[self.db]
fields = self.model._meta.local_concrete_fields
objs = list(objs)
self._populate_pk_values(objs)
with transaction.atomic(using=self.db, savepoint=False):
if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
and self.model._meta.has_auto_field):