簡體   English   中英

有沒有辦法在序列化數據之后只獲取查詢集中的特定字段,而不在 drf 中創建不同的序列化程序?

[英]Is there a way to get only specific fields in a queryset after serialization data, without create a different serializer in drf?

我需要在要獲取特定字段的地方進行查詢,然后對其進行序列化並僅保留我在查詢中獲得的特定字段。

模型.py

class Search(models.Model):
    NEUTRAL = 'None'
    POSITIVE = 'P'
    NEGATIVE = 'N'
    POLARITY_CHOICES = [
        (NEUTRAL, 'Neutral'),
        (POSITIVE, 'Positive'),
        (NEGATIVE, 'Negative'),
    ]
    user = models.ForeignKey(User,related_name='searched_user_id',on_delete=models.CASCADE)
    word = models.CharField( max_length = 100)
    social_network = models.ForeignKey(SocialNetwork,related_name='search_social_network_id',on_delete=models.CASCADE)
    polarity = models.CharField(
        max_length=4,
        choices=POLARITY_CHOICES,
        default=NEUTRAL,
    )
    sentiment_analysis_percentage = models.FloatField(default=0)
    topic = models.ForeignKey(Topic,related_name='search_topic_id',on_delete=models.CASCADE)
    liked = models.IntegerField(default=0)  
    shared = models.IntegerField(default=0) 
    is_active = models.BooleanField(default=True)
    is_deleted = models.BooleanField(default=False)
    updated_date=models.DateTimeField(auto_now=True)
    searched_date = models.DateTimeField(auto_now_add=True)

序列化程序.py

class SearchSerializer(serializers.ModelSerializer):
    searched_date = serializers.DateTimeField(format="%d-%m-%Y")
    class Meta:
        model = Search
        fields = ('__all__')

class RecentSearchSerializer(serializers.ModelSerializer):
    searched_date = serializers.DateTimeField(format="%d-%m-%Y")
    class Meta:
        model = Search
        fields = ('user','social_network','word','searched_date')

class SentimentAnalysisSerializer(serializers.ModelSerializer):
    searched_date = serializers.DateTimeField(format="%d-%m-%Y")
    class Meta:
        model = Search
        fields = ('polarity','searched_date','sentiment_analysis_percentage')

SearchSerializer 是搜索的主要序列化器,RecentSearchSerializer 是在 DRF api 視圖中傳遞數據和過濾的序列化器,最后我創建了 SentimentAnalysisSerializer 來保留我需要的特定字段:

api.py

class SearchViewSet(viewsets.ModelViewSet):
    queryset = Search.objects.filter(
        is_active=True,
        is_deleted=False
    ).order_by('id')
    permission_classes = [
        permissions.AllowAny
    ]
    serializer_class = SearchSerializer
    pagination_class = StandardResultsSetPagination

    def __init__(self,*args, **kwargs):
        self.response_data = {'error': [], 'data': {}}
        self.code = 0

    def get_serializer_class(self):
        if self.action in ['recent_search','word_details']:
            return RecentSearchSerializer
        return SearchSerializer

    @action(methods=['post'], detail=False)
    def word_details(self, request, *args, **kwargs):
        try:
            self.response_data['data']['word'] = kwargs['data']['word']
            queryset = Search.objects.filter(
                is_active=True,
                is_deleted=False,
                social_network=kwargs['data']['social_network'],
                user_id=kwargs['data']['user'],
                word=kwargs['data']['word']
            ).order_by('id')
            import pdb;pdb.set_trace()
            serializer = SentimentAnalysisSerializer(queryset, many=True)
            self.response_data['data']['timeline_word_twitter_polarity'] = json.loads(json.dumps(serializer.data))

我做了這個解決方案並且效果很好,但是有沒有辦法在不創建另一個序列化程序的情況下擁有相同的行為? 我的意思是,使用 SearchSerializer?

我嘗試了以下示例,但我得到了這些錯誤:

(Pdb) queryset = Search.objects.filter(is_active=True,is_deleted=False,social_network=kwargs['data']['social_network'],user_id=kwargs['data']['user'],word=kwargs['data']['word']).values('polarity','sentiment_analysis_percentage','searched_date').order_by('id')
(Pdb) serializer = RecentSearchSerializer(queryset, many=True)
(Pdb) self.response_data['data']['timeline_word_twitter_polarity'] = json.loads(json.dumps(serializer.data))
*** KeyError: "Got KeyError when attempting to get a value for field `user` on serializer `RecentSearchSerializer`.\nThe serializer field might be named incorrectly and not match any attribute or key on the `dict` instance.\nOriginal exception text was: 'user'."
(Pdb) 
(Pdb) queryset = Search.objects.filter(is_active=True,is_deleted=False,social_network=kwargs['data']['social_network'],user_id=kwargs['data']['user'],word=kwargs['data']['word']).values('polarity','sentiment_analysis_percentage','searched_date').order_by('id')
(Pdb) serializer = SearchSerializer(queryset, many=True)
(Pdb) self.response_data['data']['timeline_word_twitter_polarity'] = json.loads(json.dumps(serializer.data))
*** KeyError: "Got KeyError when attempting to get a value for field `word` on serializer `SearchSerializer`.\nThe serializer field might be named incorrectly and not match any attribute or key on the `dict` instance.\nOriginal exception text was: 'word'."

首先我認為這些錯誤與這個問題有關,但是根據這個答案,我沒有像問題解釋那樣傳遞data參數,所以我無法檢查驗證方法的錯誤(is_valid())

我正在使用 DRF 的最新版本:djangorestframework==3.10.3

我希望得到這個結果,但使用 SearchSerializer (我需要對特定字段進行其他查詢,我的意思是我不需要傳遞 Search Model 的所有字段),但我不知道這是否可能

(Pdb) serializer = SentimentAnalysisSerializer(queryset, many=True)
(Pdb) self.response_data['data']['timeline_word_twitter_polarity'] = json.loads(json.dumps(serializer.data))
(Pdb) self.response_data['data']['timeline_word_twitter_polarity']
[{'searched_date': '09-10-2019', 'polarity': 'P', 'sentiment_analysis_percentage': 0.0}, {'searched_date': '09-10-2019', 'polarity': 'N', 'sentiment_analysis_percentage': 0.0}]

在此先感謝,任何幫助將不勝感激。

好吧,錯誤很明顯。

您將查詢限制為使用values僅返回某些字段。 因此,序列化程序無法序列化它,因為很多都丟失了。

但是,以下方法應該適合您。

注意:我不喜歡這個 - 我寧願像你一樣擁有 2 個單獨的序列化器。 但它可能會幫助你。

class SearchSerializer(serializers.ModelSerializer):
    searched_date = serializers.DateTimeField(format="%d-%m-%Y")
    class Meta:
        model = Search
        fields = ('__all__')

    def __init__(self, instance=None, data=empty, **kwargs):
        super(SearchSerializer, self).__init__(instance, data, **kwargs)
        if instance is not None and instance._fields is not None:     
            allowed = set(instance._fields)
            existing = set(self.fields.keys())
            for fn in existing - allowed:
                self.fields.pop(fn)

基本上,它只保留提供的instance中的字段。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM