gautamw3
gautamw3

Reputation: 19

Write serializer for a model having multiple foreign key in django rest framework

I am building an api for CRUD operations on a user table which has association with country and state tables as given model definitions:

class Country(models.Model):
""" Model for Country"""
country_abbreviation = models.CharField(max_length=80)
country_name = models.CharField(max_length=80)
is_active = models.SmallIntegerField()

def __str__(self):
    return self.country_name


class State(models.Model):
""" model for saving state"""
state_name = models.CharField(max_length=32)
state_abbreviation = models.CharField(max_length=8)
country = models.ForeignKey(Country, related_name='states', on_delete=models.CASCADE)
is_active = models.SmallIntegerField(default=1, blank=True)

def __str__(self):
    return self.state_name

class Meta:
    """ meta class"""
    ordering = ('state_name', )

class User(models.Model):
""" model for saving user information """
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
country = models.ForeignKey(Country, related_name='user_country', on_delete=models.CASCADE)
state = models.ForeignKey(State, related_name='user_state', on_delete=models.CASCADE)
address = models.CharField(max_length=150)

def __str__(self):
    return '%d: %s %s' % (self.id, self.first_name, self.last_name)

class Meta:
    """ meta class """
    ordering = ('first_name', )

I am writing serializers in a way that while I am getting records from user table, for every row in the table there must be available all the country and state info associated with that particular row instead of just their ids respectively:

class UserSerializer(serializers.ModelSerializer):

class Meta:
    model = User
    fields = ['id', 'first_name', 'last_name', 'country', 'state', 'address']

Expected response :

{ 
"count": 1,
"next": null,
"previous": null,
"results": [ 
    { 
        "id": 1,
        "first_name": "Satish",
        "last_name": "Kumar",
        "country": { 
            "id": 23,
            "country_name": "India" 
        }, 
        "state": { 
            "id": 22,
            "state_name": "Delhi"
        },
        "address": "New Delhi" 
    } 
],
"page_size": 10, 
"model_type": "User" 

}

I am getting:

{
"count": 1,
"next": null,
"previous": null,
"results": [
    {
        "id": 1,
        "first_name": "Satish",
        "last_name": "Kumar",
        "country": 23,
        "state": 22,
        "address": "New Delhi"
    }
],
"page_size": 10,
"model_type": "User"

}

In the views.py the codes look like:

class UserList(generics.ListCreateAPIView):
filter_backends = [filters.SearchFilter, filters.OrderingFilter]
search_fields = ['first_name', 'last_name']
ordering_fields = ['id', 'first_name', 'last_name']
ordering = ['first_name']
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]

def list(self, request, *args, **kwargs):
    page_size_req = self.request.query_params.get('page_size', None)
    if page_size_req is not None:
        records_per_page = page_size_req
        pagination.PageNumberPagination.page_size = int(page_size_req)
    else:
        records_per_page = 10
    response = super().list(request, args, kwargs)
    # Add additional info required:
    response.data['page_size'] = records_per_page
    response.data['model_type'] = 'User'
    return response

Can someone please help me figure out, how I can achieve the desired results in this case? Thanks for your time in advance.

Upvotes: 0

Views: 1098

Answers (1)

ruddra
ruddra

Reputation: 51948

In that case, add depth to your serializer:

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ['id', 'first_name', 'last_name', 'country', 'state', 'address']
        depth = 1

Upvotes: 3

Related Questions