Django实现同表sessions字段加10存入totalsessions字段方法
核心问题
现有代码存在3个明显问题导致需求无法实现:
- 仅对
sessions字段做了累加赋值,完全没有编写totalsessions的赋值逻辑,该字段自然不会更新持久化 - 先手动修改实例调用
save(),再绑定request.data做序列化校验的逻辑冗余,还可能被前端传入的非法值覆盖计算好的sessions数值 - 序列化器未显式包含
totalsessions字段时,返回结果不会携带该字段值,前端无法拿到数据渲染表格
修改方案
1. 重写视图逻辑(views.py)
用数据库原子累加避免并发计算错误,去掉冗余的序列化校验逻辑,同时更新两个字段:
from django.db.models import F from rest_framework import status from rest_framework.decorators import api_view from rest_framework.response import JsonResponse from django.shortcuts import get_object_or_404 from .models import Swimmers from .serializers import SubSerializer @api_view(['POST']) def swimmersReduce(request, pk): # 校验对应游泳者实例存在 sw = get_object_or_404(Swimmers, id=pk) # 数据库层面原子更新两个字段,避免并发场景下数值累加错误 # F表达式直接在数据库侧取值计算,不需要先把数据读到内存 Swimmers.objects.filter(id=pk).update( sessions=F('sessions') + 10, totalsessions=F('sessions') + 10 ) # 刷新内存中实例的字段值,拿到最新的计算结果 sw.refresh_from_db() # 直接序列化最新实例返回,不需要接收前端传值校验,避免非法数据覆盖 serializer = SubSerializer(instance=sw) return JsonResponse(serializer.data, safe=False, status=status.HTTP_200_OK)
注:你提到的「点击按钮后前端表格新增一行」属于前端逻辑,后端只需要返回更新后的完整字段值即可,前端拿到返回的
totalsessions后直接追加表格行即可,不需要后端在Swimmers表新增记录。
2. 检查序列化器配置
确认SubSerializer的字段列表包含totalsessions,否则返回结果不会携带该字段:
from rest_framework import serializers from .models import Swimmers class SubSerializer(serializers.ModelSerializer): class Meta: model = Swimmers fields = [ 'id', 'name', 'lastname', 'idno', 'sessions', 'totalsessions', 'dateofpayment' ]
3. (可选)模型层自动同步字段
如果项目里还有其他地方会更新sessions字段,可以重写模型的save方法,自动同步sessions值到totalsessions,避免漏更:
from django.db import models class Swimmers(models.Model): name = models.CharField(max_length=200, blank=False) lastname = models.CharField(max_length=200, blank=False) idno = models.CharField(max_length=200, blank=False, null=True) sessions = models.IntegerField(blank=False) totalsessions = models.IntegerField(blank=True, null=True) dateofpayment = models.CharField(max_length=200, blank=True) def save(self, *args, **kwargs): # sessions赋值时自动同步到totalsessions if self.sessions is not None: self.totalsessions = self.sessions super().save(*args, **kwargs)
添加该逻辑后,视图层不需要再手动写totalsessions的更新逻辑,只要sessions变更,save时会自动同步。
注意事项
- 不要在内存中读取实例字段值计算后再保存,高并发场景下会出现多个请求读到同一个旧值,导致累加结果错误,用
F()表达式可以完全避免这个问题 - 该接口的逻辑是固定累加10,不需要前端传入任何业务字段,不要把
request.data传给序列化器校验,防止前端伪造字段值篡改数据 - 接口返回200状态码即可,原代码用201状态码不符合REST规范,201用于资源创建场景,该接口是更新操作
内容的提问来源于stack exchange,提问作者d3vkidhash
相关产品推荐
相关产品推荐

