DRF中能否通过SlugRelatedField实现Word模型的正向查询?
期望输出格式
slides = [ { "id": "1", "sentence": "The person is in the house.", "sentence-type": "simple", "clauses": { "type": "independent clause", "description": "An independent clause has a subject and a verb. An independent clause expresses a complete thought." }, "wordlist": [ { "pos": "article", "pos_description": "An article modifies a noun like an adjective does and are considered necessary to provide proper syntax to a sentence.", "colour": "21 128 61", "word": "the" } ] } ]
现有模型定义
class Sentence(models.Model): sentence = models.CharField(max_length=500) # 注:实际需补充sentence_type字段以匹配输出需求
class Word(models.Model): word = models.CharField(max_length=255) part_of_sentence = models.ForeignKey(PartOfSentence, related_name='pos_word', on_delete=models.CASCADE, blank=True, null=True) words = models.ForeignKey(Sentence, related_name='sentence_word', on_delete=models.CASCADE, blank=True, null=True)
class PartOfSentence(models.Model): part_of_sentence = models.CharField(max_length=20) pos_colour = models.CharField(max_length=20) pos_description = models.CharField(max_length=512)
class Clause(models.Model): TYPES = ( ('NONE', 'None'), ('INDEPENDENT', 'Independent'), ('DEPENDENT', 'Dependent'), ('COORDINATING_CONJUNCTION', 'Coordinating-Conjunction'), ('SUBORDINATING_CONJUNCTION', 'Subordinating-Conjunction') ) clause = models.CharField(choices=TYPES, max_length=40, default='None')
当前序列化器定义
class ClauseSerializer(serializers.ModelSerializer): class Meta: model = Clause fields = ('clause',)
class SentenceSerializer(serializers.ModelSerializer): clause = ClauseSerializer() words = serializers.SlugRelatedField( source='sentence_word', slug_field='word', many=True, read_only=True ) class Meta: model = Sentence fields = ('sentence', 'sentence_type', 'clause', 'words')
当前序列化输出
[ { "sentence": "the person is in the house", "sentence_type": "SIMPLE", "clause": { "clause": "INDEPENDENT", "description": "An independent clause has a subject and a verb. An independent clause expresses a complete thought" }, "words": [ "the", "person", "is" ] } ]
问题
当前输出的words数组仅包含单词字符串,缺少词性(pos)、词性描述(pos_description)、颜色(colour)等关键信息,咨询是否可以通过SlugRelatedField实现Word模型的正向查询,以获取完整的单词相关结构。
解答
不能用SlugRelatedField实现这个需求。SlugRelatedField的核心作用是序列化出关联模型的单个字段值(比如仅返回word字段的字符串),无法生成包含多字段的对象结构。要获取Word模型及关联PartOfSentence的完整信息,必须使用嵌套序列化器,具体修改步骤如下:
1. 编写PartOfSentence序列化器
用于序列化词性相关的描述和颜色字段:
class PartOfSentenceSerializer(serializers.ModelSerializer): class Meta: model = PartOfSentence fields = ('part_of_sentence', 'pos_description', 'pos_colour')
2. 编写Word序列化器
映射期望输出的字段名,同时关联PartOfSentence的信息:
class WordSerializer(serializers.ModelSerializer): # 映射字段名以匹配期望输出 pos = serializers.CharField(source='part_of_sentence.part_of_sentence') pos_description = serializers.CharField(source='part_of_sentence.pos_description') colour = serializers.CharField(source='part_of_sentence.pos_colour') class Meta: model = Word fields = ('word', 'pos', 'pos_description', 'colour')
3. 修改Sentence序列化器
替换SlugRelatedField为WordSerializer,并调整字段名匹配期望输出:
class ClauseSerializer(serializers.ModelSerializer): # 调整Clause序列化器以匹配期望的输出结构 type = serializers.SerializerMethodField() description = serializers.SerializerMethodField() def get_type(self, obj): # 将choices值转换为友好名称,比如INDEPENDENT转为"independent clause" if obj.clause == 'INDEPENDENT': return "independent clause" # 可补充其他类型的转换逻辑 return obj.get_clause_display().lower() def get_description(self, obj): # 返回对应从句类型的描述文本 if obj.clause == 'INDEPENDENT': return "An independent clause has a subject and a verb. An independent clause expresses a complete thought." return "" class Meta: model = Clause fields = ('type', 'description') class SentenceSerializer(serializers.ModelSerializer): clauses = ClauseSerializer() # 字段名改为clauses匹配期望输出 wordlist = WordSerializer(source='sentence_word', many=True, read_only=True) # 替换SlugRelatedField为嵌套序列化器 class Meta: model = Sentence fields = ('id', 'sentence', 'sentence_type', 'clauses', 'wordlist') # 加入id字段,调整字段名匹配期望输出
关键说明
- SlugRelatedField仅适用于需要返回单个字段值的场景,无法满足多字段对象的序列化需求;
- 嵌套序列化器可以完整序列化关联模型的所有需要的字段,包括跨模型关联的信息(比如Word关联的PartOfSentence数据);
- 通过
source参数可以灵活映射模型字段到输出的字段名,确保和期望格式一致。
内容的提问来源于stack exchange,提问作者miriad
相关产品推荐
相关产品推荐

