如何在Django的Movie模型中实现starring字段多选Actor?
实现Movie模型starring字段的Actor多选功能
问题背景
在crew应用中有继承自抽象模型Parent的Actor模型:
from django.db import models # Create your models here. class Parent(models.Model): # name=models.CharField(max_length=30,unique=True,default=None) name=models.CharField(max_length=30,unique=True,default=None) about=models.TextField(max_length=2000,blank=True,null=True) class Meta: abstract = True def __str__(self): return self.name class Actor(Parent): slug=models.SlugField(max_length=50,unique=True) photo=models.ImageField(upload_to='crew/actor')
需要将其关联到movie应用中Movie模型的starring字段,实现多选Actor的功能。当前该字段使用ForeignKey仅支持单个Actor选择,Movie模型代码如下:
from django.db import models from django.contrib.auth.models import User from crew.models import * from review_awards.models import * # Create your models here. class Movie(models.Model): name=models.CharField(max_length=100,unique=True,blank=True) slug=models.SlugField(max_length=100,unique=True,blank=True) year=models.CharField(max_length=5,blank=True) language=models.CharField(max_length=50,blank=True) poster=models.ImageField(upload_to='movies/poster') cover=models.ImageField(upload_to='movies/cover',null=True) duration=models.CharField(max_length=50,default=None) streaming=models.ForeignKey(Streaming,on_delete=models.CASCADE,blank=True,null=True) ott=models.TextField(max_length=50,blank=True,null=True) starring=models.ForeignKey(Actor,on_delete=models.CASCADE,related_name='actor',blank=True,null=True) director=models.ForeignKey(Director,on_delete=models.CASCADE,blank=True,null=True) cinematographer=models.ForeignKey(Cinematographer,on_delete=models.CASCADE,null=True,blank=True) writer=models.CharField(max_length=100,blank=True) based =models.CharField(max_length=100,blank=True,null=True) genre=models.CharField(max_length=100,blank=True) awards=models.ForeignKey(Award,on_delete=models.CASCADE,null=True,blank=True) critic_reviews=models.ForeignKey(Critic_Review,on_delete=models.CASCADE,null=True,blank=True) audience_reviews=models.ForeignKey(Audience_Review,on_delete=models.CASCADE,null=True,blank=True) rating=models.CharField(max_length=20,blank=True) certification=models.ForeignKey(Certification,on_delete=models.CASCADE,null=True,blank=True) synopsis=models.TextField(max_length=1000,blank=True) trailer=models.TextField(max_length=50,blank=True) def __str__(self): return self.name
解决方案
1. 替换字段类型为ManyToManyField
将Movie模型中的starring字段从ForeignKey改为ManyToManyField:
# 替换前 starring=models.ForeignKey(Actor,on_delete=models.CASCADE,related_name='actor',blank=True,null=True) # 替换后 starring=models.ManyToManyField(Actor, related_name='starred_movies', blank=True)
ManyToManyField无需设置on_delete参数,多对多关系的关联数据删除逻辑由Django自动处理。- 修改
related_name为starred_movies,语义更清晰,后续可通过actor.starred_movies.all()快速查询该演员参演的所有电影。
2. 执行数据库迁移
修改模型后,生成并应用迁移文件以更新数据库结构:
python manage.py makemigrations python manage.py migrate
3. 优化Admin界面(可选)
若要在Django后台更便捷地选择多个Actor,可在Movie的Admin类中添加分栏选择配置:
from django.contrib import admin from .models import Movie class MovieAdmin(admin.ModelAdmin): filter_horizontal = ('starring',) # 水平分栏展示选择器 # 也可使用 filter_vertical = ('starring',) 垂直分栏 admin.site.register(Movie, MovieAdmin)
关联数据查询示例
- 获取某部电影的所有主演:
movie.starring.all() - 获取某演员参演的所有电影:
actor.starred_movies.all()
内容的提问来源于stack exchange,提问作者Hari
相关产品推荐
相关产品推荐

