django - 基于自定义 SQL 和自定义 Django 函数创建检查约束
问题描述
问题是关于在检查约束中使用自定义函数:
我有以下模型:
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;
True
如果 DB 中有超过 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
完美运行
user
现在我想创建一个检查约束,如果 DB 中已经有 3 个或更多条目并且ip
相同,则不允许在 DB 中保存任何新条目。
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 开始,可以使用返回布尔值的表达式,因此使用 Q 没有意义
models.CheckConstraint(
name='max_3_ips',
check=IpCount(models.F('user_id'), models.Value(2)),
), ]
推荐阅读
- java - 除非还有一个失效监听器,否则属性不会调用更改监听器,这是怎么回事?
- python-3.x - 无法用正方形填充 Python tkinter/turtle 窗口
- android - InMobi 横幅广告未加载
- liferay - 在不使用控制面板的情况下部署和修改 Portlet
- r - 在 R NSE 中使用带空参数的 quos
- entity-framework - WebApi2 GET 总是说发生了错误
- node.js - 带有 node.js 的 ArangoDB 中的数据库类型错误
- iphone - 如果我将我的 iPhone 应用程序设置为包含 Facebook 登录,我可以访问有关用户参与的 Facebook 群组的信息吗?
- tensorflow - 使输出更稀疏
- r - 用 lmerTest 创建的扫帚整理对象不起作用