Django中艺人视频关联查询及中间类创建方法咨询
Django 模型与视图问题解答
1. 在views.py中实现点击艺人展示其专属视频的查询逻辑
给你两种常用实现方式,选适合你项目风格的就行:
函数视图写法
from django.shortcuts import get_object_or_404, render from .models import Artist, Video def artist_videos(request, artist_id): # 获取指定艺人,找不到就返回404页面 artist = get_object_or_404(Artist, id=artist_id) # 直接通过多对多关联拿到该艺人的所有视频 videos = artist.artist_videos.all() # 把数据传给模板渲染 return render(request, 'your_template.html', {'artist': artist, 'videos': videos})
然后在urls.py配置对应路由:
path('artist/<int:artist_id>/videos/', views.artist_videos, name='artist_videos'),
模板里直接循环videos就能展示内容了。
类视图写法(更简洁)
用Django自带的DetailView,它会自动处理对象获取逻辑:
from django.views.generic.detail import DetailView from .models import Artist class ArtistVideoDetailView(DetailView): model = Artist template_name = 'your_template.html' context_object_name = 'artist'
路由配置:
path('artist/<int:pk>/videos/', ArtistVideoDetailView.as_view(), name='artist_videos'),
模板里直接用{{ artist.artist_videos.all }}遍历视频即可。
2. 当前模型存在的几个小问题
我帮你梳理了几个需要优化的点:
- Artist的图片上传路径:
upload_to='media'会把图片存在MEDIA_ROOT/media/下,有点冗余,建议改成upload_to='artist_pics'这类更清晰的路径,避免和默认media目录混淆。 - Video的默认封面:
video_image默认值是image.png,要确保这个文件存在于MEDIA_ROOT或STATIC_ROOT中,否则页面渲染时会出现图片加载失败的问题。 - Video的描述字段:用
TextField却加了max_length=100有点矛盾——TextField是用来存长文本的,如果是短描述,不如换成CharField(max_length=100);如果需要存长内容,就删掉max_length限制。 - Video的发布时间:
auto_now=True会在每次保存视频(比如修改信息)时更新时间,如果你要的是仅创建时记录的发布时间,应该改成auto_now_add=True。 - 视频内容完整性:
video_file和video_embed_link都允许为空,最好加个验证确保至少填其中一个,避免出现无内容的空视频。可以重写模型的clean()方法:
from django.core.exceptions import ValidationError class Video(models.Model): # ... 其他字段 ... def clean(self): super().clean() if not self.video_file and not self.video_embed_link: raise ValidationError("必须上传视频文件或填写嵌入链接")
3. 是否需要创建中间类?
什么时候需要?
如果艺人与视频的关系只需要“关联”,不需要额外信息(比如视频被艺人收录的时间、在艺人列表中的排序权重等),那默认的多对多关系就足够,不需要自定义中间类。
但如果需要在关联中存储额外字段,就必须创建自定义中间模型。
如何创建中间类并查询?
比如我们要添加“视频被艺人添加的时间”字段:
from django.db import models # 自定义中间模型 class ArtistVideo(models.Model): artist = models.ForeignKey(Artist, on_delete=models.CASCADE) video = models.ForeignKey(Video, on_delete=models.CASCADE) added_date = models.DateTimeField(auto_now_add=True) # 额外字段:视频被添加的时间 class Meta: unique_together = ('artist', 'video') # 避免同一个艺人重复关联同一个视频 # 修改Artist模型的多对多字段,指定关联的中间模型 class Artist(models.Model): artist_picture = models.ImageField(upload_to='artist_pics') artist_name = models.CharField(max_length=100) artist_videos = models.ManyToManyField(Video, through=ArtistVideo) def __str__(self): return self.artist_name
查询某艺人的所有视频
即使加了中间模型,原来的简单查询依然有效:
artist = get_object_or_404(Artist, id=1) videos = artist.artist_videos.all()
如果要用到中间表的额外字段(比如按添加时间倒序排列),可以这样写:
videos = Video.objects.filter(artistvideo__artist=artist).order_by('-artistvideo__added_date')
内容的提问来源于stack exchange,提问作者Aron Chalz
相关产品推荐
相关产品推荐

