<p>我有一个<a href="https://stackoverflow.com/a/53608043/2996101">similar issue</a>,当一个用户实例被保存时,我试图添加一个组。在</p>
<p>发生这种情况的原因是在<a href="https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#the-save-method" rel="nofollow noreferrer">docs</a>处,更明确地说是在<a href="https://code.djangoproject.com/ticket/30022#comment:4" rel="nofollow noreferrer">this ticket</a>处(使用代码)。在</p>
<p>当保存<code>ModelForm()</code>(在管理中点击save)时,首先保存对象的一个实例,然后触发它的所有信号等。第三步是使用<code>ModelForm().cleaned_data</code>保存所有m2m关系。如果<code>ModelForm().cleaned_data['tags']</code>是{<cd4>},则从信号创建的所有关系都将被删除。在</p>
<ul>
<li><p>一个黑客的解决方案是使用<code>post_save</code>信号和<a href="https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.on_commit" rel="nofollow noreferrer">^{<cd6>}</a>信号,它将在现有事务(包括保存所有m2m关系的过程)提交到数据库后执行相关代码。在</p>
<pre><code>def on_transaction_commit(func):
''' Create the decorator '''
def inner(*args, **kwargs):
transaction.on_commit(lambda: func(*args, **kwargs))
return inner
@receiver(post_save, sender=Photo)
@on_transaction_commit
def tags(instance, raw, **kwargs):
"""
Create the relevant tags after the transaction
of instance is committed, unless the database is
populated with fixtures.
"""
if not raw:
update_tags(instance)
</code></pre></li>
<li><p>如果您的多对多关系没有<code>blank=True</code>,一个更合理的解决方案是使用<a href="https://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed" rel="nofollow noreferrer">^{<cd8>}</a>信号,如前所述<a href="https://stackoverflow.com/questions/23795811/django-accessing-manytomany-fields-from-post-save-signal">in this post</a>或前面提到的<a href="https://code.djangoproject.com/ticket/30022#comment:4" rel="nofollow noreferrer">ticket</a>。</p></li>
<li><p>最好的方法是<a href="https://lincolnloop.com/blog/django-anti-patterns-signals/" rel="nofollow noreferrer">ditch the signals</a>并在使用<code>ModelForm()</code>的情况下重写<code>ModelForm().clean()</code>方法,如果直接保存模型,也重写<code>Model().save()</code>方法。在</p>
<p>一个<code>ModelForm().instance.my_flag</code>将很有用,因此您可以检查<code>Model().save()</code>中是否存在{<cd13>},以避免访问两次数据库。</p></li>
</ul>