<p>假设这对您的设计是一个很强的约束,我会让数据库知道并在数据库本身上实施它。相应的SQL如下所示:</p>
<pre><code>ALTER TABLE "myapp_subscribers" ADD CONSTRAINT "myapp_subscribers_not_self" CHECK (user1_id <> user2_id)
</code></pre>
<p>将<code>user1_id</code>和<code>user2_id</code>替换为实际的字段名,<code>myapp_</code>替换为应用程序的实际名称,<code>not_self</code>替换为您想赋予约束的任何名称,只要它的目的对您来说是显而易见的,就无所谓了</em></p>
<p>虽然Django没有为这类事情提供自动化,但是自己编写一个定制的迁移步骤是相当容易的。如果要创建新的应用程序,请在Django生成的迁移文件中,将此添加到迁移步骤列表的末尾:</p>
<pre><code>migrations.RunSQL(
[('ALTER TABLE "myapp_subscribers" ADD CONSTRAINT "myapp_subscribers_not_self" CHECK (user1_id <> user2_id);', None)],
[('ALTER TABLE "myapp_subscribers" DROP CONSTRAINT "myapp_subscribers_not_self";', None)]
)
</code></pre>
<p>第二个SQL行允许反转操作。如果忽略它,Django将拒绝向后运行迁移</p>
<p>如果要更改现有应用程序,请将其包含在正在创建的迁移中,或者创建一个空迁移</p>
<pre><code>./manage.py makemigrations empty myapp
</code></pre>
<p>添加约束后,数据库将强制执行该约束,并阻止任何尝试(无论是来自django还是其他任何东西)将用户订阅给他自己</p>
<p>在Django方面,这意味着任何这样做的尝试都会引起<a href="https://docs.djangoproject.com/en/1.8/ref/exceptions/#django.db.IntegrityError" rel="nofollow">^{<cd5>}</a>。如果在<a href="https://docs.djangoproject.com/en/1.8/topics/db/transactions/#controlling-transactions-explicitly" rel="nofollow">transaction</a>中,这也会导致事务完全回滚</p>