首页 > 解决方案 > 通过模型序列化过滤嵌套的 DRF

问题描述

我的每个模型都继承自基本模型,其中包含publishing_status 帮助我控制对象是否包含在返回数据中的字段。

class BaseModel(models.Model):
    class PublishingStatus(models.TextChoices):
        ACCEPTED = 'accepted', 'Accepted'
        REJECTED = 'rejected', 'Rejected'

    publishing_status = models.CharField(
        max_length=9,
        choices=PublishingStatus.choices,
        default=PublishingStatus.DRAFT,
        help_text="Publishing status represents the state of the object. By default it is 'draft'"
    )

    class Meta:
        abstract = True

这是两个模型WordHomonym它们都继承自BaseModel

class Word(BaseModel):
    definition = models.CharField(max_length=255)
    homonyms = models.ManyToManyField('self', through='Homonym', through_fields=('homonym', 'word'))


class Homonym(BaseModel):
    homonym = models.ForeignKey(Word, on_delete=models.CASCADE, related_name="homonyms")
    word = models.ForeignKey(Word, on_delete=models.CASCADE, related_name="word_homonyms")

同音词基本上也是单词,所以我在这里有自我参考,但是通过模型Homonym,我可以控制这些关系是否公开或不用于我的网站。

然后按照序列化程序,可能应该在此处传递解决方案:

class HomonymSerializer(serializers.ModelSerializer):
    class Meta:
        model = Homonym
        fields = '__all__'


class WordSerializer(serializers.ModelSerializer):
    homonyms = HomonymSerializer(many=True)
    
    class Meta:
        model = Word
        fields = '__all__'

问题:目前,无论是否接受,都会显示所有同音异义词。如何将嵌套序列化程序限制为仅包含与 ? 的同音词publishing_status="accepted"

这是我的看法:

class WordRetrieveView(RetrieveAPIView):
    serializer_class = WordSerializer
    queryset = Word.objects.all().filter(publishing_status='accepted')

我目前的解决方案是将homonyms字段定义为SerializerMethodField()并在此处过滤查询集(我感觉这不是最好的方式,也不是 django 方式):

class WordSerializer(serializers.ModelSerializer):
        homonyms = serializers.SerializerMethodField()
        
        class Meta:
            model = Word
            fields = '__all__'

        @staticmethod
        def get_homonyms(obj):
            homonyms = Homonym.objects.all().filter(publishing_status='accepted', homonym_id=obj.id)
            return [HomonymSerializer(Word.objects.get(id=h.homonym_id)).data for h in homonyms]

bdbd的方法

已删除的HomonymSerializer
删除get_homonyms方法WordSerializer

class WordSerializer(serializers.ModelSerializer):            
        class Meta:
            model = Word
            fields = '__all__'

class WordRetrieveView(RetrieveAPIView):
    serializer_class = WordSerializer
    queryset = Word.objects.all().filter(publishing_status='accepted').prefetch_related(
        Prefetch('homonyms', queryset=Homonym.objects.filter(publishing_status='accepted'))
    )

标签: djangodjango-rest-framework

解决方案


您的主要查询集只会影响返回的结果Word,而不是相关的同音词。因此,如果您只想返回某个子集,您还需要对相关对象应用相同的过滤器。

在这种情况下,只需将查询集更改为:

Word.objects.filter(publishing_status='accepted').prefetch_related(
    Prefetch('homonyms', queryset=Homonym.objects.filter(publishing_status='accepted'))
)

这将获得所有Word被接受的 s,以及每个被接受的单词的任何相关同音异义词。


推荐阅读