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

Django实现DB日期记录仅存单条 支持多次更新不新增条目

问题修复方案

核心问题原因

原有接口逻辑每次接收POST请求时,直接将传入数据传给序列化器执行save(),没有提前查询对应freeze_date的存量记录,因此每次请求都会触发数据库INSERT操作生成新条目。

修改步骤

1. 调整模型层,增加唯一约束

从数据库层面兜底保证同一个冻结日期仅存在一条记录,避免并发场景下出现重复数据,修改Models.py代码:

import datetime
from django.db import models

class FreezePrimaryCategory(models.Model):
    # 给freeze_date加unique=True约束,禁止同日期重复记录
    freeze_date = models.DateField(default=datetime.datetime.now, unique=True)
    updated_date = models.DateTimeField(auto_now=True)

    def __str__(self) -> str:
        return str(self.freeze_date)

注意:添加该字段后需要执行python manage.py makemigrations和python manage.py migrate同步数据库结构,如果库中已经存在重复的freeze_date记录,需要先手动清理重复数据再执行迁移,否则会报错。

2. 调整视图层逻辑,实现存在即更新、不存在则新建

修改Views.py的POST方法逻辑,提交时先查询对应freeze_date是否已有记录,有则传实例给序列化器走更新逻辑,无则走新建逻辑,同时保留原有权限、装饰器逻辑:

from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from .models import FreezePrimaryCategory
from .serializers import FreezeCategorySerializer
# 保留原有IsAuthenticated、checkToken等导入不变

class FreezePrimaryCategory(APIView):
    permission_classes = (IsAuthenticated,)

    @checkToken
    def post(self, request):
        freeze_date = request.data.get("freeze_date")
        # 先查对应日期的存量记录
        exist_instance = FreezePrimaryCategory.objects.filter(freeze_date=freeze_date).first()

        serializer = FreezeCategorySerializer(
            instance=exist_instance,
            data={"freeze_date": freeze_date}
        )
        if serializer.is_valid():
            serializer.save()
            # 新建返回201,更新返回200,符合REST接口规范
            resp_status = status.HTTP_201_CREATED if exist_instance is None else status.HTTP_200_OK
            return Response(serializer.data, status=resp_status)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

3. 序列化器无需改动

原有Serializers.py的日期校验逻辑完全兼容新逻辑,不管是新建还是更新场景,序列化器都会自动执行validate方法做日期合法性判断;模型层的updated_date字段配置了auto_now=True,每次执行save()都会自动更新为当前时间,完全符合需求,原有代码保留即可:

from datetime import date
from rest_framework import serializers
from .models import FreezePrimaryCategory

class FreezeCategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = FreezePrimaryCategory
        fields = ['freeze_date']

    def validate(self, data):
        today = date.today()
        if data['freeze_date'] >= today:
            raise serializers.ValidationError('Date cannot be greater than current Date')
        return data

效果验证

  • 首次提交未入库的freeze_date:正常新建记录,返回201状态码,updated_date自动生成
  • 重复提交相同freeze_date:直接更新原有记录,不生成新条目,updated_date自动刷新为本次请求时间
  • 提交大于等于当日的日期:正常触发校验返回400错误,原有校验逻辑不受影响

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 12:12:22