ValueError: save() prohibited to prevent data loss due to unsaved related object

2,172 views
Skip to first unread message

Mike Dewhirst

unread,
Oct 16, 2015, 8:30:07 PM10/16/15
to django...@googlegroups.com
I think I understand this error and I like what it does. My question is ...

What is the necessary coding paradigm when you have all sorts of m:1,
1:m and m:m relationships and need to create those objects when they
don't exist when saving a new central object?

I'm moving from 1.7.x to 1.8.5 and this error seems like a show-stopper
at the moment.

Thanks

Mike

Tim Graham

unread,
Oct 17, 2015, 3:28:30 PM10/17/15
to Django users
Do you have code that worked before (didn't result in data loss) but doesn't work now? If so, it could be a bug in Django.

Mike Dewhirst

unread,
Oct 18, 2015, 2:19:10 AM10/18/15
to django...@googlegroups.com
On 18/10/2015 6:28 AM, Tim Graham wrote:
> Do you have code that worked before (didn't result in data loss) but
> doesn't work now? If so, it could be a bug in Django.

Yes indeed. It is all in my repo. I'll go back to 1.7.x and rerun the
tests and report back.

Thanks

Mike

>
> On Friday, October 16, 2015 at 8:30:07 PM UTC-4, Mike Dewhirst wrote:
>
> I think I understand this error and I like what it does. My question
> is ...
>
> What is the necessary coding paradigm when you have all sorts of m:1,
> 1:m and m:m relationships and need to create those objects when they
> don't exist when saving a new central object?
>
> I'm moving from 1.7.x to 1.8.5 and this error seems like a show-stopper
> at the moment.
>
> Thanks
>
> Mike
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To post to this group, send email to django...@googlegroups.com
> <mailto:django...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/a96af71f-3ad2-4789-9c91-c297f5cf4f89%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/a96af71f-3ad2-4789-9c91-c297f5cf4f89%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.

Mike Dewhirst

unread,
Oct 20, 2015, 2:42:57 AM10/20/15
to django...@googlegroups.com
On 18/10/2015 5:18 PM, Mike Dewhirst wrote:
> On 18/10/2015 6:28 AM, Tim Graham wrote:
>> Do you have code that worked before (didn't result in data loss) but
>> doesn't work now? If so, it could be a bug in Django.
>
> Yes indeed. It is all in my repo. I'll go back to 1.7.x and rerun the
> tests and report back.

It took a while but I can run 623 tests successfully under 1.6.11 and
1.7.10 but not under 1.8.5.

The above error is occurring in my setUp() method.

I run the tests via a batch file which does a dumpdata for the necessary
fixtures after migrating any changes. There were some Django migrations
in the move to 1.8.5 and I reloaded the local database from the staging
server which is running Django 1.6. Here is the traceback ...

(xxfx3) C:\Users\mike\env\xxfx3\ssds>run-local test
substance.tests.test_aerosol
Migrations for 'substance':
0042_auto_20151020_1501.py:
- Alter field chronic_metric on aquatic
- Alter field dose_units on exposure
Operations to perform:
Synchronize unmigrated apps: messages, admindocs, staticfiles, common
Apply all migrations: regulation, refer, auth, sessions, company,
contenttypes, workplace, substance, sites, credit, admin
Synchronizing apps without migrations:
Creating tables...
Running deferred SQL...
Installing custom SQL...
Running migrations:
Rendering model states... DONE
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying substance.0042_auto_20151020_1501... OK
.
copying substance\fixtures\test_data.json to
substance\fixtures\initial_data.json
.
1 file(s) copied.

dev settings

Python: 3.4
Django: 1.8.5
Database: ssds.climate.com.au
Postgres: 9.1
15:02:33

Ssds Admin = mi...@dewhirst.com.au
BASE_DIR = C:/Users/mike/env/xxfx3/ssds (project root)
SETTINGS_DIR = C:/Users/mike/env/xxfx3/ssds/ssds/settings
MEDIA_ROOT = C:/var/www/media/ssds/ (store uploaded images)
MEDIA_URL = <website>/media/ (serve uploaded images)
STATIC_ROOT = C:/var/www/static/ssds/ (collectstatic dest)
STATIC_URL = <website>/static/ (serve css, js etc)
STATICFILES_DIRS# 1 = C:/Users/mike/env/xxfx3/ssds/static/
STATICFILES_DIRS# 2 = C:/Users/mike/env/xxfx3/ssds/company/static/
STATICFILES_DIRS# 3 = C:/Users/mike/env/xxfx3/ssds/substance/static/
STATICFILES_DIRS# 4 = C:/Users/mike/env/xxfx3/ssds/workplace/static/
TEMPLATE_DIRS# 1 = C:/Users/mike/env/xxfx3/ssds/templates/

test settings

Python: 3.4
Django: 1.8.5
Database: ssds.climate.com.au
Postgres: 9.1
Testing: SQLite3 in memory
15:02:33

Creating test database for alias 'default'...
E
======================================================================
ERROR: test_aerosol_deflagration_density_fail
(substance.tests.test_aerosol.TestAerosol)

----------------------------------------------------------------------
Traceback (most recent call last):
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 405, in get_or_create
return self.get(**lookup), False
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 334, in get
self.model._meta.object_name
substance.models.substance.DoesNotExist: Substance matching query does
not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 405, in get_or_create
return self.get(**lookup), False
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 334, in get
self.model._meta.object_name
substance.models.wrappedsds.DoesNotExist: Wrapped_Sds matching query
does not exist.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "C:\Users\mike\env\xxfx3\ssds\substance\tests\test_aerosol.py",
line 36, in setUp
division=div, url_sds='x')
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 407, in get_or_create
return self._create_object_from_params(lookup, params)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 439, in _create_object_from_params
obj = self.create(**params)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 348, in create
obj.save(force_insert=True, using=self.db)
File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
line 318, in save
self._post_save()
File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
line 337, in _post_save
self.recreate_hazards()
File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
line 896, in recreate_hazards
sds = self.get_next_editable_sds()
File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
line 774, in get_next_editable_sds
sds = sdsutils.find_next_sds(self)
File "C:\Users\mike\env\xxfx3\ssds\substance\sdsutils.py", line 107,
in find_next_sds
return construct_sds(Sds, substance, sds_old, make_new)
File "C:\Users\mike\env\xxfx3\ssds\substance\sdsutils.py", line 113,
in construct_sds
sds = Sds.objects.create(substance=substance)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 348, in create
obj.save(force_insert=True, using=self.db)
File "C:\Users\mike\env\xxfx3\ssds\substance\models\sds.py", line
192, in save
region=wrapper.region)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 407, in get_or_create
return self._create_object_from_params(lookup, params)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 439, in _create_object_from_params
obj = self.create(**params)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
line 348, in create
obj.save(force_insert=True, using=self.db)
File "C:\Users\mike\env\xxfx3\ssds\substance\models\wrappedsds.py",
line 60, in save
super(Wrapped_Sds, self).save(*args, **kwargs)
File
"C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\base.py",
line 685, in save
"unsaved related object '%s'." % field.name
ValueError: save() prohibited to prevent data loss due to unsaved
related object 'sds'.

----------------------------------------------------------------------
Ran 1 test in 9.579s

FAILED (errors=1)
Destroying test database for alias 'default'...
--

Climate Pty Ltd
PO Box 308
Mount Eliza
Vic 3930
Australia +61

T: 03 9787 6598
M: 0411 704 143



Tim Graham

unread,
Oct 20, 2015, 8:46:59 AM10/20/15
to Django users
Could you provide a minimal example project that reproduces the error?

Mike Dewhirst

unread,
Oct 21, 2015, 2:45:58 AM10/21/15
to django...@googlegroups.com
On 20/10/2015 11:46 PM, Tim Graham wrote:
> Could you provide a minimal example project that reproduces the error?

Clever question!!!

In cutting stuff out to achieve minimal I discovered what my problem is.

1. substance.save() ensures that sds exists or is created

2. sds.save() ensures that sds_wrapper exists or is created

The solution is to move the sds_wrapper portion of the code back to one
of the substance methods. In particular, get_next_editable_sds() so if
the sds_wrapper needs to be created it is done from there.

As usual, there is nothing wrong with Django. I should have done this in
the first place rather than launch into print. Sorry for bothering you
and ...

Thanks

Mike


>
> On Tuesday, October 20, 2015 at 2:42:57 AM UTC-4, Mike Dewhirst wrote:
>
> On 18/10/2015 5:18 PM, Mike Dewhirst wrote:
> > On 18/10/2015 6:28 AM, Tim Graham wrote:
> >> Do you have code that worked before (didn't result in data loss)
> but
> >> doesn't work now? If so, it could be a bug in Django.
> >
> > Yes indeed. It is all in my repo. I'll go back to 1.7.x and rerun
> the
> > tests and report back.
>
> It took a while but I can run 623 tests successfully under 1.6.11 and
> 1.7.10 but not under 1.8.5.
>
> The above error is occurring in my setUp() method.
>
> I run the tests via a batch file which does a dumpdata for the
> necessary
> fixtures after migrating any changes. There were some Django migrations
> in the move to 1.8.5 and I reloaded the local database from the staging
> server which is running Django 1.6. Here is the traceback ...
>
> (xxfx3) C:\Users\mike\env\xxfx3\ssds>run-local test
> substance.tests.test_aerosol
> Migrations for 'substance':
> Â Â 0042_auto_20151020_1501.py:
> Â Â Â - Alter field chronic_metric on aquatic
> Â Â Â - Alter field dose_units on exposure
> Operations to perform:
> Â Â Synchronize unmigrated apps: messages, admindocs, staticfiles,
> common
> Â Â Apply all migrations: regulation, refer, auth, sessions, company,
> contenttypes, workplace, substance, sites, credit, admin
> Synchronizing apps without migrations:
> Â Â Creating tables...
> Â Â Â Running deferred SQL...
> Â Â Installing custom SQL...
> Running migrations:
> Â Â Rendering model states... DONE
> Â Â Applying contenttypes.0002_remove_content_type_name... OK
> Â Â Applying auth.0002_alter_permission_name_max_length... OK
> Â Â Applying auth.0003_alter_user_email_max_length... OK
> Â Â Applying auth.0004_alter_user_username_opts... OK
> Â Â Applying auth.0005_alter_user_last_login_null... OK
> Â Â Applying auth.0006_require_contenttypes_0002... OK
> Â Â Applying substance.0042_auto_20151020_1501... OK
> Â Â Â Â Â Â Â Â Â .
> copying substance\fixtures\test_data.json to
> substance\fixtures\initial_data.json
> Â Â Â Â Â Â Â Â Â .
> Â Â Â Â Â 1 file(s) copied.
>
> dev settings
>
> Python: Â 3.4
> Django: Â 1.8.5
> Database: ssds.climate.com.au <http://ssds.climate.com.au>
> Postgres: 9.1
> 15:02:33
>
> Ssds Admin     = mi...@dewhirst.com.au <javascript:>
> BASE_DIR      = C:/Users/mike/env/xxfx3/ssds  (project
> root)
> SETTINGS_DIR Â Â Â = C:/Users/mike/env/xxfx3/ssds/ssds/settings
> MEDIA_ROOT Â Â Â Â = C:/var/www/media/ssds/ Â Â Â Â Â (store
> uploaded images)
> MEDIA_URL Â Â Â Â Â = <website>/media/ Â Â Â Â Â Â Â
> Â (serve uploaded images)
> STATIC_ROOT Â Â Â Â = C:/var/www/static/ssds/ Â Â Â Â
> (collectstatic dest)
> STATIC_URL Â Â Â Â = <website>/static/ Â Â Â Â Â Â Â
> (serve css, js etc)
> STATICFILES_DIRS# 1 = C:/Users/mike/env/xxfx3/ssds/static/
> STATICFILES_DIRS# 2 = C:/Users/mike/env/xxfx3/ssds/company/static/
> STATICFILES_DIRS# 3 = C:/Users/mike/env/xxfx3/ssds/substance/static/
> STATICFILES_DIRS# 4 = C:/Users/mike/env/xxfx3/ssds/workplace/static/
> TEMPLATE_DIRS# 1 Â Â = C:/Users/mike/env/xxfx3/ssds/templates/
>
> test settings
>
> Python: Â 3.4
> Django: Â 1.8.5
> Database: ssds.climate.com.au <http://ssds.climate.com.au>
> Postgres: 9.1
> Testing: Â SQLite3 in memory
> 15:02:33
>
> Creating test database for alias 'default'...
> E
> ======================================================================
> ERROR: test_aerosol_deflagration_density_fail
> (substance.tests.test_aerosol.TestAerosol)
>
> ----------------------------------------------------------------------
> Traceback (most recent call last):
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 405, in get_or_create
> Â Â Â return self.get(**lookup), False
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 334, in get
> Â Â Â self.model._meta.object_name
> substance.models.substance.DoesNotExist: Substance matching query does
> not exist.
>
> During handling of the above exception, another exception occurred:
>
> Traceback (most recent call last):
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 405, in get_or_create
> Â Â Â return self.get(**lookup), False
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 334, in get
> Â Â Â self.model._meta.object_name
> substance.models.wrappedsds.DoesNotExist: Wrapped_Sds matching query
> does not exist.
>
> During handling of the above exception, another exception occurred:
>
> Traceback (most recent call last):
> Â Â File
> "C:\Users\mike\env\xxfx3\ssds\substance\tests\test_aerosol.py",
> line 36, in setUp
> Â Â Â division=div, url_sds='x')
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
>
> line 127, in manager_method
> Â Â Â return getattr(self.get_queryset(), name)(*args, **kwargs)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 407, in get_or_create
> Â Â Â return self._create_object_from_params(lookup, params)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 439, in _create_object_from_params
> Â Â Â obj = self.create(**params)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 348, in create
> Â Â Â obj.save(force_insert=True, using=self.db)
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
> line 318, in save
> Â Â Â self._post_save()
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
> line 337, in _post_save
> Â Â Â self.recreate_hazards()
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
> line 896, in recreate_hazards
> Â Â Â sds = self.get_next_editable_sds()
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\models\substance.py",
> line 774, in get_next_editable_sds
> Â Â Â sds = sdsutils.find_next_sds(self)
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\sdsutils.py", line
> 107,
> in find_next_sds
> Â Â Â return construct_sds(Sds, substance, sds_old, make_new)
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\sdsutils.py", line
> 113,
> in construct_sds
> Â Â Â sds = Sds.objects.create(substance=substance)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
>
> line 127, in manager_method
> Â Â Â return getattr(self.get_queryset(), name)(*args, **kwargs)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 348, in create
> Â Â Â obj.save(force_insert=True, using=self.db)
> Â Â File "C:\Users\mike\env\xxfx3\ssds\substance\models\sds.py", line
> 192, in save
> Â Â Â region=wrapper.region)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\manager.py",
>
> line 127, in manager_method
> Â Â Â return getattr(self.get_queryset(), name)(*args, **kwargs)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 407, in get_or_create
> Â Â Â return self._create_object_from_params(lookup, params)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 439, in _create_object_from_params
> Â Â Â obj = self.create(**params)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\query.py",
> line 348, in create
> Â Â Â obj.save(force_insert=True, using=self.db)
> Â Â File
> "C:\Users\mike\env\xxfx3\ssds\substance\models\wrappedsds.py",
> line 60, in save
> Â Â Â super(Wrapped_Sds, self).save(*args, **kwargs)
> Â Â File
> "C:\Users\mike\env\xxfx3\lib\site-packages\django\db\models\base.py",
> line 685, in save
> Â Â Â "unsaved related object '%s'." % field.name <http://field.name>
> ValueError: save() prohibited to prevent data loss due to unsaved
> related object 'sds'.
>
> ----------------------------------------------------------------------
> Ran 1 test in 9.579s
>
> FAILED (errors=1)
> Destroying test database for alias 'default'...
>
>
>
> >
> > Thanks
> >
> > Mike
> >
> >>
> >> On Friday, October 16, 2015 at 8:30:07 PM UTC-4, Mike Dewhirst
> wrote:
> >>
> >> Â Â I think I understand this error and I like what it does.
> My question
> >> Â Â is ...
> >>
> >> Â Â What is the necessary coding paradigm when you have all
> sorts of m:1,
> >> Â Â 1:m and m:m relationships and need to create those objects
> when they
> >> Â Â don't exist when saving a new central object?
> >>
> >> Â Â I'm moving from 1.7.x to 1.8.5 and this error seems like a
> >> show-stopper
> >> Â Â at the moment.
> >>
> >> Â Â Thanks
> >>
> >> Â Â Mike
> >>
> >> --
> >> You received this message because you are subscribed to the Google
> >> Groups "Django users" group.
> >> To unsubscribe from this group and stop receiving emails from
> it, send
> >> an email to django-users...@googlegroups.com <javascript:>
> >> <mailto:django-users...@googlegroups.com <javascript:>>.
> >> To post to this group, send email to django...@googlegroups.com
> <javascript:>
> >> <mailto:django...@googlegroups.com <javascript:>>.
> <http://groups.google.com/group/django-users>.
> <https://groups.google.com/d/msgid/django-users/a96af71f-3ad2-4789-9c91-c297f5cf4f89%40googlegroups.com?utm_medium=email&utm_source=footer
> <https://groups.google.com/d/optout>.
> >
>
>
> --
>
> Climate Pty Ltd
> PO Box 308
> Mount Eliza
> Vic 3930
> Australia +61
>
> T: 03 9787 6598
> M: 0411 704 143
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com
> <mailto:django-users...@googlegroups.com>.
> To post to this group, send email to django...@googlegroups.com
> <mailto:django...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/88ee1cb8-48f9-423c-9257-cd9fdd1b0bca%40googlegroups.com
> <https://groups.google.com/d/msgid/django-users/88ee1cb8-48f9-423c-9257-cd9fdd1b0bca%40googlegroups.com?utm_medium=email&utm_source=footer>.
Reply all
Reply to author
Forward
0 new messages