如何从Django的Blog模型查询带英文翻译的博客列表?
从Django的Blog模型查询带英文翻译的博客列表
需求说明
需要从Blog模型出发,获取所有带有英文翻译的博客,并返回包含英文名称、英文内容和发布日期的结构化数据。
问题分析
你之前使用的Blog.objects.filter(translations__id = 2)存在两个核心问题:
- 仅筛选出关联了特定ID翻译的博客,无法批量获取所有带英文翻译的博客;
- 没有关联并提取对应的英文翻译字段,无法直接拿到
name和content数据。
正确实现方案
1. 基础查询与数据格式化
假设英文对应的语言码(LanguagesCode.code)为'en',可按以下步骤获取目标数据:
首先筛选出存在英文翻译的博客,并预加载对应的英文翻译数据(避免N+1查询问题):
from django.db import models # 筛选带英文翻译的博客,预加载对应英文翻译 english_blogs = Blog.objects.filter( translations__language_code__code='en' ).prefetch_related( models.Prefetch( 'translations', queryset=BlogTranslation.objects.filter(language_code__code='en'), to_attr='english_trans' ) ).distinct() # 去重,避免同一博客因关联翻译被多次匹配
再将查询结果转换为需要的字典格式:
result_list = [] for blog in english_blogs: # 利用unique_together约束,每个博客的英文翻译唯一 trans = blog.english_trans[0] result_list.append({ "name": trans.name, "content": trans.content, "pub_date": blog.pub_date.isoformat() # 按ISO格式输出日期,可按需调整 })
2. Django Rest Framework序列化实现
如果使用DRF,可以通过自定义序列化器简化数据输出:
from rest_framework import serializers class BlogEnglishSerializer(serializers.ModelSerializer): name = serializers.SerializerMethodField() content = serializers.SerializerMethodField() class Meta: model = Blog fields = ["name", "content", "pub_date"] def get_name(self, obj): # 获取当前博客的英文翻译名称 return obj.translations.filter(language_code__code='en').first().name def get_content(self, obj): # 获取当前博客的英文翻译内容 return obj.translations.filter(language_code__code='en').first().content
在视图中使用该序列化器:
from rest_framework.views import APIView from rest_framework.response import Response class EnglishBlogListView(APIView): def get(self, request): queryset = Blog.objects.filter( translations__language_code__code='en' ).distinct() serializer = BlogEnglishSerializer(queryset, many=True) return Response(serializer.data)
关键说明
- 请将
'en'替换为你实际存储的英文语言码(比如'en-us'); - 使用
prefetch_related和Prefetch对象可有效减少数据库查询次数,提升性能; - 添加
.distinct()是因为filter(translations__xxx)会让同一博客被关联的翻译条目重复匹配,去重后得到唯一的博客记录。
内容的提问来源于stack exchange,提问作者Ulvi
相关产品推荐
相关产品推荐

