Django+PostgreSQL音乐播放器MP3上传提示不支持文件的解决求助
Django + PostgreSQL音乐播放器MP3上传报错修复
我正在使用Django和PostgreSQL开发音乐播放器,Song模型在数据库中可正常运行,但上传.mp3格式音频文件时,会提示“不支持的文件类型”错误。以下是相关代码文件及解决方法:
相关代码文件
models.py
from django.db import models from django.contrib.auth.models import User from cloudinary.models import CloudinaryField from recordroomapp.helper import get_audio_length from .validators import validate_is_audio class Artist(models.Model): artist = models.CharField(max_length=100, unique=True) slug = models.SlugField(max_length=100, unique=True) created_on = models.DateTimeField(auto_now_add=True) def __str__(self): return self.artist class Song(models.Model): title = models.CharField(max_length=100, unique=False) slug = models.SlugField(max_length=100, unique=True) song = models.FileField( upload_to='media/', validators=[validate_is_audio], null=True) song_length = models.DecimalField( blank=True, max_digits=10, decimal_places=2, null=True) songinfo = models.ForeignKey( "Artist", on_delete=models.CASCADE, related_name='song_post', null=True) updated_on = models.DateTimeField(auto_now=True) # featured_image = CloudinaryField('image', default='placeholder') created_on = models.DateTimeField(auto_now_add=True) likes = models.ManyToManyField(User, related_name='song_likes', blank=True) class Meta: ordering = ['-created_on'] def __str__(self): return self.title def save(self, *args, **kwargs): if not self.song_length: audio_length = get_audio_length(self.song) self.song_length = f'{audio_length:.2f}' return super().save(*args, **kwargs) def number_of_likes(self): return self.likes.count() class Comment(models.Model): post = models.ForeignKey( Song, on_delete=models.CASCADE, related_name='comments') name = models.CharField(max_length=100) email = models.EmailField() body = models.TextField() created_on = models.DateTimeField(auto_now_add=True) approved = models.BooleanField(default=False) class Meta: ordering = ['created_on'] def __str__(self): return f"Comment {self.body} by {self.name}"
views.py
from django.shortcuts import render, get_object_or_404, HttpResponse from django.views import generic, View from .models import Song class SongList(generic.ListView): model = Song queryset = Song.objects.order_by('-created_on') template_name = 'index.html' class SongDetail(View): def get(self, request, slug, *args, **kwargs): queryset = Song.objects.all() post = get_object_or_404(queryset, slug=slug) comments = post.comments.filter(approved=True).order_by('-created_on') liked = False if post.likes.filter(id=self.request.user.id).exists(): liked = True return render( request, "song_detail.html", { "song": queryset, "post": post, "comments": comments, "liked": liked }, )
admin.py
from django.contrib import admin from .models import Artist, Song, Comment from django_summernote.admin import SummernoteModelAdmin @admin.register(Artist) class ArtistAdmin(SummernoteModelAdmin): list_display = ('artist', 'slug', 'created_on') search_fields = ['artist'] @admin.register(Song) class SongAdmin(SummernoteModelAdmin): prepopulated_fields = {'slug': ('title',)} list_filter = ['created_on'] summernote_fields = ('content') list_display = ('title', 'slug', 'song', 'created_on') search_fields = ['title', 'content']
validators.py(原问题代码)
import os from django.core.exceptions import ValidationError from mutagen.mp3 import MP3 def validate_is_audio(file): try: audio = MP3(file) if not audio: raise TypeError() first_file_check = True except Exception as e: first_file_check = False if not first_file_check: raise ValidationError('Unsupported file type.') valid_file_extensions = ('.mp3') ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Unacceptable file extension.')
helper.py
from mutagen.mp3 import MP3 def get_audio_length(file): audio = MP3(file) return audio.info.length
问题修复方案
1. 修正文件扩展名验证的元组定义
原validators.py中valid_file_extensions = ('.mp3')实际是字符串而非元组,导致ext.lower() not in valid_file_extensions判断逻辑失效。需改为:
valid_file_extensions = ('.mp3',)
2. 重置文件指针位置
使用MP3(file)读取文件后,文件指针会移动到末尾,后续操作(如save方法中调用get_audio_length)会无法读取文件,需要在读取后重置指针到起始位置。
修复后的validators.py
import os from django.core.exceptions import ValidationError from mutagen.mp3 import MP3 def validate_is_audio(file): first_file_check = True try: audio = MP3(file) # 重置文件指针到起始位置 file.seek(0) if not audio: raise TypeError() except Exception as e: first_file_check = False if not first_file_check: raise ValidationError('Unsupported file type.') valid_file_extensions = ('.mp3',) ext = os.path.splitext(file.name)[1] if ext.lower() not in valid_file_extensions: raise ValidationError('Unacceptable file extension.')
修复后的helper.py
from mutagen.mp3 import MP3 def get_audio_length(file): audio = MP3(file) # 重置文件指针,避免后续上传失败 file.seek(0) return audio.info.length
3. 可选:优化save方法的异常处理
如果上传文件为空,get_audio_length会报错,建议在save方法中添加非空判断:
def save(self, *args, **kwargs): if self.song and not self.song_length: audio_length = get_audio_length(self.song) self.song_length = f'{audio_length:.2f}' return super().save(*args, **kwargs)
内容的提问来源于stack exchange,提问作者Fintan
相关产品推荐
相关产品推荐

