使用 Django 信号 post_save 错误 "save() prohibited to prevent data loss to do unsave related object ''myModel."
Using Django Signals post_save error "save() prohibited to prevent data loss to do unsave related object ''myModel."
Python 3.6.5 & Django 1.11
伪解释:
- 两个模型,模型 2 使用模型 1 作为外键
- 模型 1 的管理员使用模型 2 的内联
- 在 model1 上,我想得到一个缩短的 URL 并在有新条目时将其存储在 属性 中。为此,必须保存 model1,因为长 URL(我想缩短的那个)是基于 Autoslug 的。
Models.py
的相关部分
class Model1(models.Model):
name = models.CharField(max_length=100)
slug = AutoSlugField(populate_from='name', unique=True,
null=True, default=None)
class Model2(models.Model):
owner = models.ForeignKey(
'Model1',
on_delete=models.CASCADE,
)
这是我的信号...
@receiver(post_save, sender=Model1)
def shorten_url(sender, instance, created, **kwargs):
if created:
if not instance.short_url:
url_short = url_shorten(instance.get_absolute_url())
instance.short_url = url_short
post_save.disconnect(shorten_url, sender=sender)
instance.save()
post_save.connect(shorten_url, sender=sender)
return instance
else:
post_save.disconnect(shorten_url, sender=sender)
instance.save()
post_save.connect(shorten_url, sender=sender)
return instance
断开连接,连接是为了防止循环,我也不是 100% 确定它是正确的,但是没有它,我看到一遍又一遍地呼吁缩短 url...
我现在要解决的问题是我得到了错误
save() prohibited to prevent data loss to unsaved related object 'model1'
当我调用 save() 时。
这是回溯:
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _legacy_get_response
249. response = self._get_response(request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in wrapper
551. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/sites.py" in inner
224. return view(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in add_view
1508. return self.changeform_view(request, None, form_url, extra_context)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapper
67. return bound_func(*args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in bound_func
63. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in changeform_view
1408. return self._changeform_view(request, object_id, form_url, extra_context)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in _changeform_view
1449. self.save_related(request, form, formsets, not add)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in save_related
1003. self.save_formset(request, form, formset, change=change)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in save_formset
991. formset.save()
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save
649. return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save_new_objects
783. self.new_objects.append(self.save_new(form, commit=commit))
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save_new
927. obj.save()
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py" in save
762. "unsaved related object '%s'." % field.name
Exception Type: ValueError at /admin/wa/model1/add/
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'model1'.
我假设这是因为我在 model1 上 post_save 并且我有 model2 行在等待 model1 键错误不是这样说的。如果错误说 model2 对我来说更有意义,但事实并非如此。
在查看引发错误的 base.py 行 762 时,它似乎也在处理未保存(无 PK)对象的这种情况,但是再次......我在这里 post_save我不是吗?
另一个更新
为了进一步解决这个问题,我提交了内联表单部分没有数据的管理表单(即 Model2 中没有数据)。当我这样做时,我在 Model1 中得到两个条目,每个条目都没有 PK ... PK==None。哇。
感谢您的帮助!
为了未来...
需要注意的关键点是,当我发现没有生成 ID 时,如果你点击它,你应该想想......最近还有什么变化。
就我而言,几天前,我在我的开发箱上从 SQLITE3 更改为 PostgreSQL,以期在生产中做同样的事情。但是,我的程序存在缺陷,令人高兴的是我有一个完美运行的 READ 数据库,但是 none 的 ID 是在写入时自动生成的。
在我的例子中,我使用了 PGLOADER 来加载数据。不要那样做。
使用 Django 工具转储数据和加载数据。
Python 3.6.5 & Django 1.11
伪解释:
- 两个模型,模型 2 使用模型 1 作为外键
- 模型 1 的管理员使用模型 2 的内联
- 在 model1 上,我想得到一个缩短的 URL 并在有新条目时将其存储在 属性 中。为此,必须保存 model1,因为长 URL(我想缩短的那个)是基于 Autoslug 的。
Models.py
的相关部分class Model1(models.Model):
name = models.CharField(max_length=100)
slug = AutoSlugField(populate_from='name', unique=True,
null=True, default=None)
class Model2(models.Model):
owner = models.ForeignKey(
'Model1',
on_delete=models.CASCADE,
)
这是我的信号...
@receiver(post_save, sender=Model1)
def shorten_url(sender, instance, created, **kwargs):
if created:
if not instance.short_url:
url_short = url_shorten(instance.get_absolute_url())
instance.short_url = url_short
post_save.disconnect(shorten_url, sender=sender)
instance.save()
post_save.connect(shorten_url, sender=sender)
return instance
else:
post_save.disconnect(shorten_url, sender=sender)
instance.save()
post_save.connect(shorten_url, sender=sender)
return instance
断开连接,连接是为了防止循环,我也不是 100% 确定它是正确的,但是没有它,我看到一遍又一遍地呼吁缩短 url...
我现在要解决的问题是我得到了错误
save() prohibited to prevent data loss to unsaved related object 'model1'
当我调用 save() 时。
这是回溯:
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _legacy_get_response
249. response = self._get_response(request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in wrapper
551. return self.admin_site.admin_view(view)(*args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
57. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/sites.py" in inner
224. return view(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in add_view
1508. return self.changeform_view(request, None, form_url, extra_context)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapper
67. return bound_func(*args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
149. response = view_func(request, *args, **kwargs)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/utils/decorators.py" in bound_func
63. return func.__get__(self, type(self))(*args2, **kwargs2)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in changeform_view
1408. return self._changeform_view(request, object_id, form_url, extra_context)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in _changeform_view
1449. self.save_related(request, form, formsets, not add)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in save_related
1003. self.save_formset(request, form, formset, change=change)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/contrib/admin/options.py" in save_formset
991. formset.save()
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save
649. return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save_new_objects
783. self.new_objects.append(self.save_new(form, commit=commit))
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/forms/models.py" in save_new
927. obj.save()
File "/home/username/.virtualenvs/project/lib/python3.6/site-packages/django/db/models/base.py" in save
762. "unsaved related object '%s'." % field.name
Exception Type: ValueError at /admin/wa/model1/add/
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'model1'.
我假设这是因为我在 model1 上 post_save 并且我有 model2 行在等待 model1 键错误不是这样说的。如果错误说 model2 对我来说更有意义,但事实并非如此。
在查看引发错误的 base.py 行 762 时,它似乎也在处理未保存(无 PK)对象的这种情况,但是再次......我在这里 post_save我不是吗?
另一个更新
为了进一步解决这个问题,我提交了内联表单部分没有数据的管理表单(即 Model2 中没有数据)。当我这样做时,我在 Model1 中得到两个条目,每个条目都没有 PK ... PK==None。哇。
感谢您的帮助!
为了未来... 需要注意的关键点是,当我发现没有生成 ID 时,如果你点击它,你应该想想......最近还有什么变化。
就我而言,几天前,我在我的开发箱上从 SQLITE3 更改为 PostgreSQL,以期在生产中做同样的事情。但是,我的程序存在缺陷,令人高兴的是我有一个完美运行的 READ 数据库,但是 none 的 ID 是在写入时自动生成的。
在我的例子中,我使用了 PGLOADER 来加载数据。不要那样做。 使用 Django 工具转储数据和加载数据。