在保存新实例之前删除实例(Django 模型保存方法)

问题描述 投票:0回答:1

我想将模型的记录限制为每个用户最多 10 行(该模型具有用户模型的外键)。最佳实践是什么?

我考虑过重写保存方法,执行检查,然后在保存之前删除:

def save(self, *args, **kwargs):
 if MyModel.objects.filter(user=self.user).count() >= 10:
     oldest_record =         MyModel.objects.filter(user=self.user).order_by('created_at').first()
 oldest_record.delete()
 super().save(*args, **kwargs)

但我想知道这是否是一个好的解决方案,在数据库级别强制执行是否更好(以及如何做到这一点),以及同一用户同时保存两个实例时的潜在问题(尽管可能性很小)。有类似经历吗?

django django-models
1个回答
0
投票

您可以使用

user_id
而不是
user
来提高效率,因为它会阻止获取用户。

我们还可以一次获取所有项目,从而防止某些竞争条件:

def save(self, *args, **kwargs):
    if instance._state.adding:
        items = (
            MyModel.objects.filter(user_id=self.user_id)
            .order_by('created_at')
            .only('pk')[10:]
        )
    if items:
        MyModel.objects.filter(pk__in={item.pk for item in items}).delete()
    super().save(*args, **kwargs)

但是重写

.save()
方法、信号等都可以通过批量操作(例如批量创建)来规避。

如果在数据库级别强制执行更好(以及实现方法是什么)。

可以在数据库级别使用

UniqueConstraint
强制执行此操作,使
user_id
和主键模10的组合唯一。在这种情况下,逻辑将转向选择一个好的主键。

因此,这意味着对于用户来说,我们可以为其分配例如具有主键

51
26
32
等的项目,但不能再次分配
31
,因为
…1
已经被“选择” .

可能最好定期运行管理命令来清理旧记录,并且在前端始终将用户的

MyModel
数量限制为十个。这可能相当稳健。

© www.soinside.com 2019 - 2024. All rights reserved.