使用 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

伪解释:

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 工具转储数据和加载数据。