How to pass choice display name to model serialize in Django REST framework?
Question:
My env is Django 2.0.3, DRF 3.8.2 and Python 3.6.4.
I have a model in serializers.py
:
class TransferCostSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
field_view = super().to_representation(instance)
if field_view['is_active']:
return field_view
return None
class Meta:
model = TransferCost
fields = ('id', 'destination', 'total_cost', 'is_active',)
Where destination
field is choice field of 3 elements:
DESTINATION = (
('none', _('I will drive by myself')),
('transfer_airport', _('Only from airport')),
('transfer_round_trip', _('Round trip')),
)
This is my models.py
:
class TransferCost(models.Model):
destination = models.CharField(
_('Transfer Destination'), choices=DESTINATION, max_length=55
)
total_cost = models.PositiveIntegerField(
_('Total cost'), default=0
)
is_active = models.BooleanField(_('Transfer active?'), default=True)
class Meta:
verbose_name = _('Transfer')
verbose_name_plural = _('Transfers')
def __str__(self):
return _('Transfer {}').format(self.destination)
..And I return JSON like this:
[
{
id: 1,
destination: "transfer_airport",
total_cost: 25,
is_active: true
},
{
id: 2,
destination: "transfer_round_trip",
total_cost: 45,
is_active: true
}
]
How to return destination
field with his display name? For example:
[
{
id: 1,
destination_display: "Only from airport",
destination: "transfer_round_trip",
total_cost: 25,
is_active: true
},
{
id: 2,
destination_display: "Round trip",
destination: "transfer_round_trip",
total_cost: 45,
is_active: true
}
]
Would be great to have something like get_FOO_display()
in serializers.py
, but it’s not working. I need this thing, because I render form dynamically via Vue.js (as v-for
select list).
Answers:
you can use fields source with get_FOO_display
class TransferCostSerializer(serializers.ModelSerializer):
destination_display = serializers.CharField(
source='get_destination_display'
)
just place get_destination_display
withoput ()
in fields
. like this:
class TransferCostSerializer(serializers.ModelSerializer):
class Meta:
model = TransferCost
fields = ('id', 'get_destination_display', 'total_cost', 'is_active',)
In case you want to have the values of all model fields with choices to be returned as display values, following worked out for me:
from rest_framework import serializers
from django.core.exceptions import FieldDoesNotExist
class TransferCostSerializer(serializers.ModelSerializer):
class Meta:
model = TransferCost
fields = ('id', 'destination', 'total_cost', 'is_active',)
def to_representation(self, instance):
"""
Overwrites choices fields to return their display value instead of their value.
"""
data = super().to_representation(instance)
for field in data:
try:
if instance._meta.get_field(field).choices:
data[field] = getattr(instance, "get_" + field + "_display")()
except FieldDoesNotExist:
pass
return data
The other solutions dropped auto generated meta-information of the model fields, e.g., translated labels.
My env is Django 2.0.3, DRF 3.8.2 and Python 3.6.4.
I have a model in serializers.py
:
class TransferCostSerializer(serializers.ModelSerializer):
def to_representation(self, instance):
field_view = super().to_representation(instance)
if field_view['is_active']:
return field_view
return None
class Meta:
model = TransferCost
fields = ('id', 'destination', 'total_cost', 'is_active',)
Where destination
field is choice field of 3 elements:
DESTINATION = (
('none', _('I will drive by myself')),
('transfer_airport', _('Only from airport')),
('transfer_round_trip', _('Round trip')),
)
This is my models.py
:
class TransferCost(models.Model):
destination = models.CharField(
_('Transfer Destination'), choices=DESTINATION, max_length=55
)
total_cost = models.PositiveIntegerField(
_('Total cost'), default=0
)
is_active = models.BooleanField(_('Transfer active?'), default=True)
class Meta:
verbose_name = _('Transfer')
verbose_name_plural = _('Transfers')
def __str__(self):
return _('Transfer {}').format(self.destination)
..And I return JSON like this:
[
{
id: 1,
destination: "transfer_airport",
total_cost: 25,
is_active: true
},
{
id: 2,
destination: "transfer_round_trip",
total_cost: 45,
is_active: true
}
]
How to return destination
field with his display name? For example:
[
{
id: 1,
destination_display: "Only from airport",
destination: "transfer_round_trip",
total_cost: 25,
is_active: true
},
{
id: 2,
destination_display: "Round trip",
destination: "transfer_round_trip",
total_cost: 45,
is_active: true
}
]
Would be great to have something like get_FOO_display()
in serializers.py
, but it’s not working. I need this thing, because I render form dynamically via Vue.js (as v-for
select list).
you can use fields source with get_FOO_display
class TransferCostSerializer(serializers.ModelSerializer):
destination_display = serializers.CharField(
source='get_destination_display'
)
just place get_destination_display
withoput ()
in fields
. like this:
class TransferCostSerializer(serializers.ModelSerializer):
class Meta:
model = TransferCost
fields = ('id', 'get_destination_display', 'total_cost', 'is_active',)
In case you want to have the values of all model fields with choices to be returned as display values, following worked out for me:
from rest_framework import serializers
from django.core.exceptions import FieldDoesNotExist
class TransferCostSerializer(serializers.ModelSerializer):
class Meta:
model = TransferCost
fields = ('id', 'destination', 'total_cost', 'is_active',)
def to_representation(self, instance):
"""
Overwrites choices fields to return their display value instead of their value.
"""
data = super().to_representation(instance)
for field in data:
try:
if instance._meta.get_field(field).choices:
data[field] = getattr(instance, "get_" + field + "_display")()
except FieldDoesNotExist:
pass
return data
The other solutions dropped auto generated meta-information of the model fields, e.g., translated labels.