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

如何在Django中实现关联Story的Episode的episode_number自动递增

如何实现每个Story下Episode的episode_number自动递增?

我来帮你搞定这个自动编号的需求!要让每个Story对应的Episode从1开始自动递增编号,不用手动输入,咱们可以从模型调整、视图逻辑修改和序列化器优化这几个方面入手:

1. 调整Episode模型字段

首先把episode_number的null=True去掉,改成blank=True——因为我们会自动给它赋值,不需要允许为空,也不需要手动输入:

class Episode(models.Model):
    title = models.CharField(max_length=255)
    cover = models.ImageField(upload_to=upload_location)
    story = models.ForeignKey(Story, on_delete=models.CASCADE)
    created_at = models.DateTimeField(auto_now_add=True)
    # 去掉null=True,设置blank=True表示后台不需要手动填写
    episode_number = models.IntegerField(blank=True)

2. 修改视图的perform_create方法

核心逻辑是在创建Episode时,先查询当前Story下已有的最大episode_number,然后加1作为新Episode的编号;如果该Story还没有Episode,就从1开始。同时为了避免并发场景下的编号重复问题,咱们可以加上事务锁:

from django.db.models import Max
from django.db import transaction

class EpisodeView(viewsets.ModelViewSet):
    serializer_class = EpisodeSerializer
    permission_classes = [BasicAuthorizationPermissions]
    
    def get_queryset(self):
        story_id = self.kwargs['story_id']
        return Episode.objects.filter(story=story_id)
    
    def perform_create(self, serializer):
        try:
            story = Story.objects.get(pk=self.kwargs['story_id'])
        except Story.DoesNotExist:
            raise NotFound
        if self.request.user != story.author:
            raise PermissionDenied
        
        # 用事务+行锁防止并发创建时编号重复
        with transaction.atomic():
            # 锁定当前Story下的所有Episode记录,避免同时写入冲突
            Episode.objects.filter(story=story).select_for_update()
            # 获取当前Story的最大episode编号
            max_episode_num = Episode.objects.filter(story=story).aggregate(max_num=Max('episode_number'))['max_num']
            # 计算新的编号:有记录就+1,无记录则从1开始
            new_episode_number = max_episode_num + 1 if max_episode_num is not None else 1
            
            # 保存时传入自动生成的编号
            return serializer.save(story=story, episode_number=new_episode_number)

3. 优化序列化器(可选但推荐)

把episode_number设置为只读字段,这样前端不需要传递这个参数,也能避免手动修改:

class EpisodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Episode
        fields = ['id', 'title', 'cover', 'story', 'created_at', 'episode_number']
        # 把episode_number设为只读,禁止前端传入
        read_only_fields = ['episode_number', 'created_at']

这样修改后,每次创建Episode时,系统会自动根据所属Story的已有Episode数量生成正确的编号,每个Story下都从1开始递增,完全不需要手动输入啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:08:34