Есть ли способ получить только определенные поля в наборе запросов после сериализации данных, не создавая другой сериализатор в drf? - PullRequest
0 голосов
/ 27 октября 2019

Мне нужно сделать запрос, в котором я хочу получить определенные поля, затем сериализовать его и сохранить только те поля, которые я получил в запросе.

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 - это основной сериализатор для поиска, RecentSearchSerializer - это сериализатор для передачи данных и фильтрации в представлении API DRF, и, наконец, я создал 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 (мне нужно сделать другие запросы с конкретными полями,я имею в виду, что мне не нужно передавать все поля модели поиска), но я не знаю, возможно ли это

(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}]

Заранее спасибо, любая помощь будет оценена.

1 Ответ

1 голос
/ 28 октября 2019

Ну, ошибки понятны.

Вы ограничиваете запрос на возврат только определенных полей, используя 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...