基于自定义 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)个具有相同 ip
和 user
.
的条目
基于这个函数,我创建了这样的 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 个或更多条目 user
和 ip
相同,则不允许在数据库中保存任何新条目。
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)),
), ]
问题是关于检查约束中自定义函数的使用:
我有以下型号:
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)个具有相同 ip
和 user
.
基于这个函数,我创建了这样的 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 个或更多条目 user
和 ip
相同,则不允许在数据库中保存任何新条目。
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)),
), ]