如何简化Django模型代码,实现多季多集影视剧的admin后台按需管理
影视站点Django模型重构方案
核心设计思路
彻底抛弃“模型内硬编码单集字段、独立模型对应单季”的冗余实现,基于Django原生外键关联搭建三层标准化结构,100%兼容原有所有功能,同时支持无上限的季、集数扩展,可直接在Admin后台按需新增条目。
- 模型结构完全符合关系型数据库设计规范,没有冗余存储字段
- 无集数、季数的存储上限,不管是小众短集剧还是长篇多季剧都能适配
- Admin后台操作逻辑和原有使用习惯一致,不需要重新适应
- 所有原有业务逻辑不需要改动,可实现平滑迁移
第一步:清理原有TvShow模型的冗余字段
直接删除TvShow模型里硬编码的episode1到episode10共10个URL字段,其余所有原有字段、自定义配置完全原封不动保留,不改动任何已有逻辑:
from django.db import models from taggit.managers import TaggableManager # 你原有编写的published自定义管理器直接导入沿用,无改动 from .managers import PublishedManager class TvShow(models.Model): # 以下字段完全和原实现保持一致 title = models.CharField(max_length=200) slug = models.SlugField(max_length=200, unique=True) author = models.ForeignKey('auth.User', on_delete=models.CASCADE, related_name='tv_shows') body = models.TextField() imdb_rating = models.DecimalField(max_digits=3, decimal_places=1) publish = models.DateTimeField() status = models.CharField(max_length=10, choices=[('draft', '草稿'), ('published', '已发布')]) views = models.PositiveIntegerField(default=0) tags = TaggableManager() # 原有管理器配置完全保留 objects = models.Manager() published = PublishedManager()
注意:这部分操作不会影响原有代码中对TvShow模型的任何查询、调用逻辑,比如你之前写的TvShow.published.filter(status='published')这类代码可以直接运行,不需要修改。
第二步:新增通用Season模型(替代逐季建独立模型的冗余方案)
不需要为每一个季度单独写模型,建一个通用的Season模型通过外键关联到所属的电视剧,仅通过季序号区分不同季度即可:
class Season(models.Model): # 外键关联到对应的电视剧实例 tv_show = models.ForeignKey( TvShow, on_delete=models.CASCADE, related_name='seasons' ) # 季序号:填1代表第1季,填2代表第2季,支持任意数量的季度 season_number = models.PositiveSmallIntegerField(help_text="季度序号") # 可选填的季标题,不需要可以留空 title = models.CharField(max_length=200, blank=True) class Meta: # 同一个电视剧下,季号不允许重复 unique_together = ('tv_show', 'season_number') # 默认按季号升序排列 ordering = ['season_number'] def __str__(self): return f"{self.tv_show.title} 第{self.season_number}季"
第三步:新增通用Episode模型(替代硬编码单集字段的方案)
用通用的Episode模型存储每一集的视频链接,通过外键关联到所属的季度,仅通过集序号区分单集,没有集数上限:
class Episode(models.Model): # 外键关联到所属的季度实例 season = models.ForeignKey( Season, on_delete=models.CASCADE, related_name='episodes' ) # 集序号:填1代表第1集,填2代表第2集,支持任意数量的单集 episode_number = models.PositiveSmallIntegerField(help_text="集序号") # 存储单集的视频链接,替代原来硬编码的10个episode字段 video_url = models.URLField(help_text="对应集数的视频播放链接") # 可选填的单集标题、简介,不需要可以留空 title = models.CharField(max_length=200, blank=True) class Meta: # 同一个季度下,集号不允许重复 unique_together = ('season', 'episode_number') # 默认按集号升序排列 ordering = ['episode_number'] def __str__(self): return f"{self.season} 第{self.episode_number}集"
第四步:配置Admin后台,实现可视化按需新增季、集
不需要写复杂的自定义Admin逻辑,通过Django原生的Inline组件配置,即可在编辑电视剧的页面直接新增季度、上传单集视频链接,操作路径和原来完全一致:
from django.contrib import admin from .models import TvShow, Season, Episode # 单集的内嵌编辑组件 class EpisodeInline(admin.TabularInline): model = Episode extra = 0 # 默认不显示空的新增行,需要时点击“新增另一个Episode”即可 verbose_name = "单集" verbose_name_plural = "单集列表" # 季度的内嵌编辑组件 class SeasonInline(admin.TabularInline): model = Season extra = 0 # 季度编辑页内嵌单集编辑功能 inlines = [EpisodeInline] verbose_name = "季度" verbose_name_plural = "季度列表" @admin.register(TvShow) class TvShowAdmin(admin.ModelAdmin): # 原有Admin配置完全保留,比如list_display、search_fields、list_filter等设置不需要改动 inlines = [SeasonInline]
原有历史数据迁移说明
你之前存在episode1到episode10字段里的历史视频链接,可以写一次性Django数据迁移脚本,自动完成迁移:
- 遍历所有TvShow实例,为每一个剧生成默认的第1季Season实例
- 逐次读取原来硬编码的10个episode字段的URL,如果值不为空,就生成对应的Episode实例,把URL写入
video_url字段,集号对应原来的字段序号 - 迁移完成后就可以彻底移除那10个旧的硬编码字段,全流程不需要手动整理数据
内容的提问来源于stack exchange,提问作者Faisal Nazik
相关产品推荐
相关产品推荐

