Вопрос относительно использования настраиваемой функции в проверочном ограничении:
У меня следующая модель:
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
, если в БД больше 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. он поддерживает логические выражения внутри ограничений chek c, но то, что я написал, не работает. Ошибка выглядит так:
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 внутри?
Спасибо