是否有一种方法可以在序列化数据后仅获取查询集中的特定字段,而无需在drf中创建其他序列化器?

问题描述 投票:0回答:1

我需要在要获取特定字段的地方进行查询,然后对其进行序列化并仅保留查询中得到的特定字段。

models.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)

serializers.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是搜索的主要序列化程序,最近的SearchSerializer是在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'."

[首先,我认为这些错误与此issue有关,但是根据此answer,我没有像问题说明那样传递data参数,所以我无法检查[ C0] Validation method

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

我希望获得此结果,但要使用SearchSerializer(我需要对特定字段进行其他查询,我是说我不需要传递Search Model的所有字段,但我不知道这是否可能

(is_valid())

感谢您,我们将不胜感激。

django python-3.x django-rest-framework
1个回答
0
投票

嗯,错误很明显。

您使用(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}] 将查询限制为仅返回某些字段。因此,串行器无法序列化,因为缺少许多。

但是,以下方法应该适合您。

注意:我不喜欢这个-我宁愿像您一样拥有2个单独的序列化器。但这可能会对您有所帮助。

values

基本上,它仅保留提供的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) 中的字段。

© www.soinside.com 2019 - 2024. All rights reserved.