You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何限制Django模型对象24小时内仅能创建一次?

实现Django模型对象的创建频率限制

针对你的需求,分两种场景给出实现方案:


一、自然日(当日0-24点)内仅允许创建一次(用unique_for_date)

首先你的模型需要关联用户(否则无法针对单个用户做限制),修改模型如下:

from django.contrib.auth.models import User
from django.db import models

class MyModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, unique_for_date='created_at')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f"{self.user.username} - {self.created_at}"

这里unique_for_date='created_at'的作用是:同一个用户在created_at对应的自然日(年月日)内,只能创建一条MyModel记录。Django会在模型验证和数据库层面(自动创建唯一索引)保证这个约束。

错误提示处理

当用户尝试重复创建时,Django会抛出IntegrityError,你可以在视图中捕获并返回友好提示:

from django.db import IntegrityError
from django.shortcuts import render, redirect
from .models import MyModel

def create_mymodel(request):
    if request.method == 'POST':
        try:
            MyModel.objects.create(user=request.user)
            return redirect('success_page')
        except IntegrityError:
            return render(request, 'create_form.html', {'error': '你今日已经创建过该记录,无法重复操作'})
    return render(request, 'create_form.html')

如果使用表单类,也可以在表单的clean方法中提前验证:

from django import forms
from .models import MyModel
from django.utils import timezone

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
        fields = []  # user和created_at自动赋值,无需用户输入

    def clean(self):
        cleaned_data = super().clean()
        user = self.request.user
        today = timezone.now().date()
        if MyModel.objects.filter(user=user, created_at__date=today).exists():
            raise forms.ValidationError('你今日已经创建过该记录,无法重复操作')
        return cleaned_data

二、任意24小时窗口内仅允许创建一次(自定义验证)

如果你的需求是从上次创建时间起算,滚动24小时内不能再次创建(而非固定自然日),unique_for_date无法满足,需要自定义验证逻辑:

1. 模型层验证

在模型中添加clean方法,在保存前做校验:

from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.core.exceptions import ValidationError

class MyModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True, blank=True)

    def clean(self):
        super().clean()
        # 检查当前用户过去24小时内是否已有记录
        twenty_four_hours_ago = timezone.now() - timezone.timedelta(hours=24)
        if MyModel.objects.filter(user=self.user, created_at__gte=twenty_four_hours_ago).exists():
            raise ValidationError('你在24小时内已经创建过该记录,请稍后再试')

    def save(self, *args, **kwargs):
        self.full_clean()  # 强制执行验证逻辑
        super().save(*args, **kwargs)

2. 错误提示处理

在视图中捕获验证错误并返回提示:

from django.core.exceptions import ValidationError
from django.shortcuts import render, redirect
from .models import MyModel

def create_mymodel(request):
    if request.method == 'POST':
        try:
            MyModel.objects.create(user=request.user)
            return redirect('success_page')
        except ValidationError as e:
            return render(request, 'create_form.html', {'error': e.message})
    return render(request, 'create_form.html')

注意:模型层的clean方法不会在bulk_create批量创建时自动执行,若有批量操作场景需要手动调用验证;高并发场景下可考虑添加数据库事务或锁来避免竞态条件。

内容的提问来源于stack exchange,提问作者Mehdi Aria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:15:46