8👍
Let’s assume that the kwdGroup
field is the relation field to a model called KeyWordGroup
.
The default ListSerializer
uses the to_representation
method to render a list of the serialized objects rest_framework :
class ListSerializer(BaseSerializer):
...
def to_representation(self, data):
"""
List of object instances -> List of dicts of primitive datatypes.
"""
# Dealing with nested relationships, data can be a Manager,
# so, first get a queryset from the Manager if needed
iterable = data.all() if isinstance(data, models.Manager) else data
return [
self.child.to_representation(item) for item in iterable
]
We can modify the ListSerializer
to group the results for example:
class VocabListSerializer(serializers.ListSerializer):
def to_representation(self, data):
iterable = data.all() if isinstance(data, models.Manager) else data
return {
kwdGroup: super().to_representation(Vocab.objects.filter(kwdGroup=kwdGroup))
for kwdGroup in KeyWordGroup.objects.all()
}
We can then use the modified VocabListSerializer
with the VocabSerializer
.
class VocabSerializer(serializers.Serializer):
...
class Meta:
list_serializer_class = VocabListSerializer
3👍
One way to achieve this is to use a SerializerMethodField. The below might be slightly different than your use case, but you can adopt accordingly. There are other ways of achieving this as well, including overwriting to_representation
methods, but they rely on messing with the inner workings of DRF more than is relevant here.
models.py
class Dictionary(Model):
id = PrimaryKey
class Word(Model):
dictionary = ForeignKey(Dictionary, related_name='words')
word = Charfield()
group = Charfield()
serializers.py
class WordSerializer(serializers.ModelSerializer):
word = serializers.CharField(read_only=True)
class Meta:
model = Word
fields = ('word',)
class DictionarySerializer(serializers.ModelSerializer):
group_a = serializers.SerializerMethodField()
group_b = serializers.SerializerMethodField()
def get_group_a(self, instance):
return WordSerializer(instance.words.filter(group='a'), many=True).data
def get_group_b(self, instance):
return WordSerializer(instance.words.filter(group='b'), many=True).data
class Meta:
model = Dictionary
fields = ('group_a', 'group_b')
An example
>>> my_dictionary = Dictionary.objects.create()
>>> Word.objects.bulk_create(
Word(word='arrow', group='a' dictionary=my_dictionary),
Word(word='apple', group='a' dictionary=my_dictionary),
Word(word='baby', group='b' dictionary=my_dictionary),
Word(word='banana', group='b' dictionary=my_dictionary)
)
>>> serializer = DictionarySerializer(my_dictionary)
>>> print serializer.data
{
'group_a': {
'word': 'arrow',
'word': 'apple'
},
'group_b': {
'word': 'baby',
'word': 'banana'
},
}
- How to set value of a ManyToMany field in Django?
- Django Generic Views: When to use ListView vs. DetailView
- Grouping dates in Django
- Django-rest-framwork got AttributeError when attempting to get a value for field
0👍
If the previously mentioned VocabListSerializer
doesn’t work, try this method:
class VocabListSerializer(serializers.ListSerializer):
child:serializers.ModelSerializer
def to_representation(self, data):
iterable:Iterable[Sentence] = data.all() if isinstance(data, models.Manager) else data
group_by_dict = {}
for item in iterable :
kwdGroup_id = item.kwdGroup.id
if kwdGroup_id in group_by_dict.keys ():
group_by_dict[kwdGroup_id].append (self.child.to_representation(item))
else :
group_by_dict [kwdGroup_id] = []
return list(group_by_dict.values())
class VocabSerializer(serializers.Serializer):
...
class Meta:
list_serializer_class = VocabListSerializer
Note that the ListSerializer
must create a list. Returning a dict like the original question requested does not seem possible by just overriding to_representation
. If you don’t use
list(group_by_dict.values())
at the end, only the list of the foreign keys (kwdGroup
) will be returned.
- How to get coordinates of address from Python
- Django: How to automatically change a field's value at the time mentioned in the same object?
- Django: set cookie on test client?
- Django create superuser from batch file
- Django and Shibboleth