I define this viewset
and i would like to create a custom function that returns distinct of animals species_type
called distinct_species
.
class AnimalViewSet(viewsets.ModelViewSet):
"""
This viewset automatically provides `list`, `create`, `retrieve`,
`update` and `destroy` actions.
"""
queryset = Animal.objects.all()
serializer_class = AnimalSerializer
@list_route()
def distinct_species(self, request):
query_set = Animal.objects.values('species_type').distinct()
serializer = self.get_serializer(query_set, many=True)
return Response(serializer.data)
This is my Animal
model
class Animal(models.Model):
this_id = models.CharField(max_length=25)
name = models.CharField(max_length=25)
species_type = models.CharField(max_length=25)
breed = models.CharField(max_length=25)
....
This is my AnimalSerializer
class AnimalSerializer(serializers.ModelSerializer):
class Meta:
model = Animal
fields = (
'this_id',
'name',
'species_type',
'breed',
...
)
read_only_fields = ('id', 'created_at', 'updated_at')
I register the route here.
# Create a router and register our viewsets with it.
router = DefaultRouter()
router.register(r'animal', AnimalViewSet)
urlpatterns = [
url(r'^api/', include(router.urls)),
url(r'^', IndexView.as_view(), name='index'),
]
But when i do this /api/animal/distinct_species/
I got this KeyError:
u"Got KeyError when attempting to get a value for field
this_id
on serializerAnimalSerializer
.\nThe serializer field might be named incorrectly and not match any attribute or key on thedict
instance.\nOriginal exception text was: u'this_id'."
In function-based views, we can pass extra context to serializer with “context” parameter with a dictionary. To access the extra context data inside the serializer we can simply access it with “self. context”. From example, to get “exclude_email_list” we just used code 'exclude_email_list = self.
Your code is using serializer only for validation, but it is possible use it to insert or update new objects on database calling serializer. save() . To save foreign keys using django-rest-framework you must put a related field on serializer to deal with it. Use PrimaryKeyRelatedField .
The trouble stems from this one:
query_set = Animal.objects.values('species_type').distinct()
Your query_set
object now a list of dictionaries. The dictionary contains exactly one field - species_type
[{'species_type': 'a'},{'species_type': 'b'},...]
Thus it does not have a this_id
which your serializer requires. If you were on postgresql, you could change your query to
query_set = Animal.objects.distinct('species_type')
Second option is to list all the fields required by the serializer in the values
() call
Third option is to create a different serializer for use by the distinct_species
end point this serializer will not be a ModelSerializer
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With