0

I'm doing a university project that requires me to implement a Web App using an API as backend and I've decided to use DRF to do it but I'm having some troubles right now.

I'm trying to override the list method in View to only show some fields when retrieving the list of all airports' records but still all fields are being returned in the Response.

Model:

class Airport(models.Model):
    code = models.CharField(max_length=10)
    name = models.TextField()
    carriers = models.ManyToManyField(Carrier, related_name='airports')

    def __str__(self):
        return self.name

Serializer:

class AirportSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Airport
        fields = ('id', 'name', 'code', 'url', 'carriers')

View:

class AirportView(viewsets.ModelViewSet):
    queryset = models.Airport.objects.all()
    serializer_class = AirportSerializer

    def list(self, request):
        airports = models.Airport.objects.only('id', 'name', 'code')
        data = AirportSerializer(airports, many=True, context={'request': request}).data
        return Response(data)

Response:

{
        "id": 4,
        "name": "Leo",
        "code": "Test",
        "url": "http://localhost:8000/api/airports/4/",
        "carriers": []
    },
    {
        "id": 5,
        "name": "asdasd",
        "code": "aasdasd",
        "url": "http://localhost:8000/api/airports/5/",
        "carriers": [
            "http://localhost:8000/api/carriers/1/"
        ]
    },
    {
        "id": 6,
        "name": "asdasd",
        "code": "aasdasd",
        "url": "http://localhost:8000/api/airports/6/",
        "carriers": [
            "http://localhost:8000/api/carriers/1/"
        ]
    }

How can I solve this? Is there a better way to do it, I mean not using QuerySet.only method?

murthaA
  • 371
  • 1
  • 4
  • 14
  • You can get some help from this post https://stackoverflow.com/questions/27935558/dynamically-exclude-or-include-a-field-in-django-rest-framework-serializer – Sanip Mar 14 '19 at 11:04

3 Answers3

3

You should define a separate serializer and return that.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • But whý is there an only() method in the QuerySet then? – murthaA Mar 14 '19 at 10:56
  • 1
    Strange question. It's there for the time when you want to retrieve only certain elements in your queryset. But the queryset does not control what is returned in DRF response, that is the job of the serializer. – Daniel Roseman Mar 14 '19 at 11:00
  • Oh now it makes sense to me the queryset only works with the model and db records the serializer is just validating stuff, thanks :). – murthaA Mar 14 '19 at 11:02
0

It is the serializer that defines how objects are serialized, not how you filter the data from the database. Currently, you have all fields available in the serializer. If you do not want some fields to be returned while listing or retrieving items, you can define those fields in the serializer as write_only, like this:

class AirportSerializer(serializers.HyperlinkedModelSerializer):
    url = serializer.CharField(write_only=True)
    carriers = serializer.PrimaryKeyRelatedField(many=True, write_only=True)

    class Meta:
        model = models.Airport
        fields = ('id', 'name', 'code', 'url', 'carriers')

This way, url and carriers fields will not be present when data is returned, but will be required while inserting data.

Ozgur Akcali
  • 5,264
  • 2
  • 31
  • 49
-2

just put the field which want in your serializer like that:

class AirportSerializer(serializers.HyperlinkedModelSerializer):
  class Meta:
     model = models.Airport
    fields = ('id', 'name', 'code')

You are good to go.

VIVEK VIKASH
  • 179
  • 6