基于自定义 SQL 和自定义 Django 函数创建检查约束

Create check constraint based on custom SQL and custom Django fucntion

问题是关于检查约束中自定义函数的使用:

我有以下型号:

class UserIP(models.Model):
    user = models.ForeignKey(
        to=User,
        on_delete=models.CASCADE,
        related_name='user_ip',
    )
    ip = models.GenericIPAddressField(
        verbose_name='User ip address'
    )
    sample_time = models.DateTimeField(
        auto_now=True,
        verbose_name='User ip sample time'
    )

我在数据库中有以下自定义函数:

create or replace function count_ips(v_ip inet , v_user_id int, v_limit int)
                               returns boolean as $$
                               select count(*) > v_limit
                               from users_userip
                               where ip = v_ip and user_id = v_user_id
                               $$ language sql;

其中 returns True 如果数据库中有 X(意味着 3)个具有相同 ipuser.

的条目

基于这个函数,我创建了这样的 Django 函数:

class IpCount(Func):
    function = 'count_ips'
    arity = 3
    output_field = BooleanField()

用法示例:

UserIP.objects.all().annotate(ann=IpCount(Value('127.0.0.1'), 1,3)).first().ann

工作完美

现在我想创建一个检查约束,如果数据库中已经有 3 个或更多条目 userip 相同,则不允许在数据库中保存任何新条目。


constraints = [
    models.CheckConstraint(
        name='max_3_ips',
        check=~models.Q(IpCount('ip', 'user_id', 3)),
    ), ]

它说从 Django > 3.1 开始。它支持 chekc 约束内的布尔表达式,但我写的内容不起作用。 错误是这样的:

 File "C:\Users\hardcase1\.virtualenvs\series-EAOB5IHD\lib\site-packages\django\db\models\query_utils.py", line 117, in deconstruct
    kwargs = {child[0]: child[1]}
TypeError: 'IpCount' object is not subscriptable

好像 Django mirations 不能序列化这个函数。

问题是 – 如何在检查约束中使用这个函数,它是否可能,或者我应该忘记它并用一堆 RAW sQL 创建自定义迁移?

谢谢

从 django 3.1 开始可以使用 returns 布尔值的表达式,因此使用 Q

没有意义
models.CheckConstraint(
                name='max_3_ips',
                check=IpCount(models.F('user_id'), models.Value(2)),
            ), ]