Django获取用户歌曲时触发ManyToMany关联ID缺失错误
问题解决方案
一、多对多关联访问错误的修复
报错的核心原因是在get方法中,你创建了一个未保存到数据库的UserProfile实例:
# 错误代码 user_prof = UserProfile(user=user)
这行代码仅在内存中生成UserProfile对象,并未从数据库读取已存在的实例,因此该对象没有id值——而Django的多对多关系必须依赖实例的主键(id)才能查询关联数据。
修复方法:和post方法一致,从数据库获取已有的UserProfile实例:
# 正确代码 user_prof = UserProfile.objects.get(user=user)
修改后的完整get方法:
def get(self, request, id='all', format=None): try: if id == 'all': user = self.request.user user_prof = UserProfile.objects.get(user=user) # 修复此处 song = user_prof.songs.all() else: song = Song.objects.get(id=id) serializer = SongSerializer(song, many=(id == 'all')) # 查询多个对象时需添加many=True return Response({ 'song': serializer.data}) except Exception as e: print('Songs:get ', e, file=sys.stderr) return Response({ 'error': 'Unable to get song' })
注意:当查询多个Song对象时,序列化器必须传入many=True参数,否则会触发序列化错误。
二、Admin中Song的notes字段不显示的修复
由于Song与Note的多对多关系使用了自定义through模型(SongNote),Django Admin默认不会自动渲染该多对多字段,可通过以下两种方式解决:
方式1:自定义字段显示关联Notes
在admin.py中修改SongAdmin类,添加自定义列展示关联的Note内容:
from django.contrib import admin from .models import Song, SongNote, Note class SongAdmin(admin.ModelAdmin): list_display = ('name', 'get_notes') def get_notes(self, obj): # 按order排序拼接Note内容 return ', '.join([note.note for note in obj.notes.all()]) get_notes.short_description = 'Notes' # 设置列名 admin.site.register(Song, SongAdmin) admin.site.register(Note) admin.site.register(SongNote)
方式2:用Inline直接管理关联关系
这种方式可以在Song的Admin页面直接编辑关联的Note和排序字段:
from django.contrib import admin from .models import Song, SongNote, Note class SongNoteInline(admin.TabularInline): model = SongNote extra = 1 # 默认显示1个空行用于添加新关联 class SongAdmin(admin.ModelAdmin): inlines = [SongNoteInline] list_display = ('name',) admin.site.register(Song, SongAdmin) admin.site.register(Note) admin.site.register(SongNote)
内容的提问来源于stack exchange,提问作者The Canadian
相关产品推荐
相关产品推荐

