假设我有一个与自身有m2m subscribers
关系的用户模型。
这个想法是用户不能自己订阅。
是否可以在模型级别处理此问题?
答案 0 :(得分:2)
您可以使用带有“m2m_changed
”操作的pre_add
信号来验证添加对象。 See docs
答案 1 :(得分:1)
假设这是对您的设计的强烈约束,我会让数据库知道它并在数据库本身上强制执行它。相应的SQL看起来像这样:
ALTER TABLE "myapp_subscribers" ADD CONSTRAINT "myapp_subscribers_not_self" CHECK (user1_id <> user2_id)
将user1_id
和user2_id
替换为实际的字段名称,将myapp_
替换为应用的实际名称,将not_self
替换为您要为其提供的名称约束,只要它的目的对你来说是显而易见的就无所谓了。
虽然Django没有为这类事情提供自动化,但是自己编写自定义迁移步骤非常容易。如果您要创建一个新应用程序,请在Django生成的迁移文件中,在迁移步骤列表的末尾添加:
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)]
)
第二个SQL行允许反转操作。如果省略它,Django将拒绝向后运行迁移。
如果要更改现有应用,请在要创建的迁移中包含该应用,或创建空迁移。
./manage.py makemigrations --empty myapp
添加约束后,数据库将强制执行该约束,并阻止任何尝试,无论是来自django还是其他任何东西,都可以将用户订阅给自己。
在Django方面,这意味着任何尝试这样做都会引发IntegrityError
。如果在transaction内,这也会导致事务干净地回滚。