Невозможно распаковать неитерабельный объект SerializerMethodField в Django DRF
Я пытаюсь присвоить список из SerializerMethodField()
return
набору из двух полей, как:
class PostSerializer(serializers.ModelSerializer):
postvotes, postvote = serializers.SerializerMethodField()
def get_postvotes(self, obj):
qset = PostVote.objects.filter(Q(post=obj))
votes = [PostVoteSerializer(m).data for m in qset]
vote = sum(vote['vote'] for vote in votes)
return [votes, vote] # votes[], vote: Integer
Однако это не удается с ошибкой, упомянутой в заголовке.
Как я могу решить эту проблему? Спасибо.
Ошибка происходит потому, что SerializerMethodField
не является итерабельным. Вы не вызываете get_postvotes()
напрямую, чтобы получить список, который он возвращает.
Чтобы решить текущую проблему, просто объявите поле как обычно:
postvotes = serializers.SerializerMethodField()
Затем, когда вы обращаетесь к значению поля postvotes
обычным способом, вы получите список из двух элементов:
votes, vote = obj.postvotes
Это изменение исправит непосредственную ошибку, но я не уверен, что оно будет работать так, как вы задумали. Поэтому вот несколько альтернативных решений:
Вместо этого используйте составное поле, например
.ListField
илиDictField
Создайте пользовательское поле, расширив
serializers.Field
. Подробности см. в документации .
Другая возможность заключается в объявлении двух SerializerMethodField
s:
votes = serializers.SerializerMethodField()
vote_count = serializers.SerializerMethodField()
Поскольку они прикреплены к методам в вашем классе сериализатора, вы можете делать все, что захотите. Например, у вас может быть вспомогательный метод для подсчета голосов:
def count_votes(self, obj):
qset = PostVote.objects.filter(Q(post=obj))
self._votes = [PostVoteSerializer(m).data for m in qset]
self._vote_count = sum(vote['vote'] for vote in votes)
Тогда вы можете просто вызвать этот метод из соответствующих методов:
def get_votes(self, obj):
if self._votes is None:
self.count_votes()
return self._votes
Аналогично для get_vote_count()
. И не забудьте инициализировать переменные-члены:
def __init__(self, *args, **kwargs):
self.super(*args, **kwargs)
self._votes = None
self._vote_count = None