mirror of
https://github.com/django/django.git
synced 2025-07-05 18:29:11 +00:00
queryset-refactor: Reorganised Model.save() to differentiate between public and private parameters. Refs #6741.
This means subclasses can override save() without needing to worry about passing around the internal parameters (an issue for subclassable models, which would have meant every model, since you don't know when somebody will subclass your model). Slightly backwards incompatible, since it moves "raw" back to being part of the internal API (it's only needed by the serializer and was intended to be internal use only). If external code really needs this, they can call Model.save_base() and pass in raw there. git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7221 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
619576002d
commit
3176bebffd
@ -167,7 +167,7 @@ class DeserializedObject(object):
|
||||
# This ensures that the data that is deserialized is literally
|
||||
# what came from the file, not post-processed by pre_save/save
|
||||
# methods.
|
||||
models.Model.save(self.object, raw=True)
|
||||
models.Model.save_base(self.object, raw=True)
|
||||
if self.m2m_data and save_m2m:
|
||||
for accessor_name, object_list in self.m2m_data.items():
|
||||
setattr(self.object, accessor_name, object_list)
|
||||
|
@ -253,19 +253,34 @@ class Model(object):
|
||||
raise TypeError, "'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]
|
||||
dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
|
||||
|
||||
def save(self, raw=False, cls=None):
|
||||
def save(self):
|
||||
"""
|
||||
Save the current instance. Override this in a subclass if you want to
|
||||
control the saving process.
|
||||
"""
|
||||
self.save_base()
|
||||
|
||||
save.alters_data = True
|
||||
|
||||
def save_base(self, raw=False, cls=None):
|
||||
"""
|
||||
Does the heavy-lifting involved in saving. Subclasses shouldn't need to
|
||||
override this method. It's separate from save() in order to hide the
|
||||
need for overrides of save() to pass around internal-only parameters
|
||||
('raw' and 'cls').
|
||||
"""
|
||||
if not cls:
|
||||
dispatcher.send(signal=signals.pre_save, sender=self.__class__,
|
||||
instance=self, raw=raw)
|
||||
cls = self.__class__
|
||||
meta = self._meta
|
||||
signal = True
|
||||
dispatcher.send(signal=signals.pre_save, sender=self.__class__,
|
||||
instance=self, raw=raw)
|
||||
else:
|
||||
meta = cls._meta
|
||||
signal = False
|
||||
|
||||
for parent, field in meta.parents.items():
|
||||
self.save(raw, parent)
|
||||
self.save_base(raw, parent)
|
||||
setattr(self, field.attname, self._get_pk_val(parent._meta))
|
||||
|
||||
non_pks = [f for f in meta.local_fields if not f.primary_key]
|
||||
@ -311,12 +326,9 @@ class Model(object):
|
||||
transaction.commit_unless_managed()
|
||||
|
||||
if signal:
|
||||
# Run any post-save hooks.
|
||||
dispatcher.send(signal=signals.post_save, sender=self.__class__,
|
||||
instance=self, created=(not record_exists), raw=raw)
|
||||
|
||||
save.alters_data = True
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
First coerces all fields on this instance to their proper Python types.
|
||||
|
@ -160,37 +160,6 @@ When you save an object, Django performs the following steps:
|
||||
is used to provide notification that an object has been successfully
|
||||
saved. (These signals are not yet documented.)
|
||||
|
||||
Raw saves
|
||||
~~~~~~~~~
|
||||
|
||||
**New in Django development version**
|
||||
|
||||
The pre-processing step (#2 in the previous section) is useful, but it modifies
|
||||
the data stored in a field. This can cause problems if you're relying upon the
|
||||
data you provide being used as-is.
|
||||
|
||||
For example, if you're setting up conditions for a test, you'll want the test
|
||||
conditions to be repeatable. If pre-processing is performed, the data used
|
||||
to specify test conditions may be modified, changing the conditions for the
|
||||
test each time the test is run.
|
||||
|
||||
In cases such as this, you need to prevent pre-processing from being performed
|
||||
when you save an object. To do this, you can invoke a **raw save** by passing
|
||||
``raw=True`` as an argument to the ``save()`` method::
|
||||
|
||||
b4.save(raw=True) # Save object, but do no pre-processing
|
||||
|
||||
A raw save skips the usual data pre-processing that is performed during the
|
||||
save. All other steps in the save (pre-save signal, data preparation, data
|
||||
insertion, and post-save signal) are performed as normal.
|
||||
|
||||
.. admonition:: When to use a raw save
|
||||
|
||||
Generally speaking, you shouldn't need to use a raw save. Disabling field
|
||||
pre-processing is an extraordinary measure that should only be required
|
||||
in extraordinary circumstances, such as setting up reliable test
|
||||
conditions.
|
||||
|
||||
Saving changes to objects
|
||||
=========================
|
||||
|
||||
|
@ -66,7 +66,8 @@ post_save_nokwargs signal
|
||||
post_save signal, Tom Smith
|
||||
Is updated
|
||||
|
||||
>>> p1.save(raw=True)
|
||||
# Calling an internal method purely so that we can trigger a "raw" save.
|
||||
>>> p1.save_base(raw=True)
|
||||
pre_save_nokwargs signal
|
||||
pre_save signal, Tom Smith
|
||||
Is raw
|
||||
|
@ -31,13 +31,13 @@ except ImportError:
|
||||
def data_create(pk, klass, data):
|
||||
instance = klass(id=pk)
|
||||
instance.data = data
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
return instance
|
||||
|
||||
def generic_create(pk, klass, data):
|
||||
instance = klass(id=pk)
|
||||
instance.data = data[0]
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
for tag in data[1:]:
|
||||
instance.tags.create(data=tag)
|
||||
return instance
|
||||
@ -45,25 +45,25 @@ def generic_create(pk, klass, data):
|
||||
def fk_create(pk, klass, data):
|
||||
instance = klass(id=pk)
|
||||
setattr(instance, 'data_id', data)
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
return instance
|
||||
|
||||
def m2m_create(pk, klass, data):
|
||||
instance = klass(id=pk)
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
instance.data = data
|
||||
return instance
|
||||
|
||||
def o2o_create(pk, klass, data):
|
||||
instance = klass()
|
||||
instance.data_id = data
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
return instance
|
||||
|
||||
def pk_create(pk, klass, data):
|
||||
instance = klass()
|
||||
instance.data = data
|
||||
models.Model.save(instance, raw=True)
|
||||
models.Model.save_base(instance, raw=True)
|
||||
return instance
|
||||
|
||||
# A set of functions that can be used to compare
|
||||
@ -309,7 +309,7 @@ def fieldsTest(format, self):
|
||||
management.call_command('flush', verbosity=0, interactive=False)
|
||||
|
||||
obj = ComplexModel(field1='first',field2='second',field3='third')
|
||||
obj.save(raw=True)
|
||||
obj.save()
|
||||
|
||||
# Serialize then deserialize the test database
|
||||
serialized_data = serializers.serialize(format, [obj], indent=2, fields=('field1','field3'))
|
||||
@ -325,7 +325,7 @@ def streamTest(format, self):
|
||||
management.call_command('flush', verbosity=0, interactive=False)
|
||||
|
||||
obj = ComplexModel(field1='first',field2='second',field3='third')
|
||||
obj.save(raw=True)
|
||||
obj.save()
|
||||
|
||||
# Serialize the test database to a stream
|
||||
stream = StringIO()
|
||||
|
Loading…
x
Reference in New Issue
Block a user