Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to get reversed nested serializers in django rest framework?

Suppose i have two models:

class Region(models.Model):
    region_name = models.CharField(
        max_length=50, null=False, blank=False, unique=True, verbose_name="Region Name"
    )
    def __str__(self):
        return self.region_name

    class Meta:
        verbose_name_plural = "Regions"

class Country(models.Model):
    region_id = models.ForeignKey(
        Region,
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        verbose_name="Region id",
    )
    country_name = models.CharField(
        max_length=50, unique=True, null=False, blank=False, verbose_name="Country Name"
    )

    def __str__(self):
        return self.country_name

    class Meta:
        verbose_name_plural = "Countries"

Now, when i access the country model through Djnago REST Framework, as /api/countries

I get country_name and region_id for example

[
  {
    "id": 1,
    "country_name":"Taiwan",
    "region_id": 1
  },
  ...
  ...
]

Is there any way to get the result like:

[
  {
    "id": 1,
    "country_name":"Taiwan",
    "region_id": {
        id: 1,
        region_name: "Asia",
      }
  },
    ...
    ...
]

I have tried nested serializer example as on the DRF website, but it returns a list of countries if we get the regions api.

like:

[
  {
    "id": 1,
    "region_name":"Asia",
    "countries": 
      [
          "Taiwan",
          "Japan",
          "Vietnam",
          ...
      ]
  },
    ...
    ...
]

I need to know the region name of the country in one api get request. Right now i am using 2 requests. One to get country, and then get region name from region id.

This is my model and serializer if i use nested serializer.

class Region(models.Model):
    region_name = models.CharField(
        max_length=50, null=False, blank=False, unique=True, verbose_name="Region Name"
    )
    def __str__(self):
        return self.region_name

    class Meta:
        verbose_name_plural = "Regions"

class Country(models.Model):
    region_id = models.ForeignKey(
        related_name="countries"
        Region,
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        verbose_name="Region id",
    )
    country_name = models.CharField(
        max_length=50, unique=True, null=False, blank=False, verbose_name="Country Name"
    )

class CountrySerializer(serializers.ModelSerializer):
    class Meta:
        model = Country
        fields = "__all__"

class RegionSerializer(serializers.ModelSerializer):
     countries = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='country_name'
     )
    class Meta:
        model = Region
        fields = ["id", "region_name", "countries"]

like image 771
Tushar Kulkarni Avatar asked Jan 21 '26 21:01

Tushar Kulkarni


1 Answers

The reason you only get the slugs of the related Countrys is because you use the SlugRelatedField, that will thus list the slugs of the Countrys.

The trick is to make extra serializers that will serializer the related object(s). For example:

class ShallowRegionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Region
        fields = '__all__'

class CountrySerializer(serializers.ModelSerializer):
    region_id = ShallowRegionSerializer()
    class Meta:
        model = Country
        fields = '__all__'

class CountryRegionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Country
        fields = '__all__'

class RegionSerializer(serializers.ModelSerializer):
     countries = CountryRegionSerializer(
        many=True,
        read_only=True
     )
    class Meta:
        model = Region
        fields = ['id', 'region_name', 'countries']

Now you can make use of the CountrySerializer and the RegionSerializer. When serializing objects, it will use other serializers, like the ShallowRegionSerializer and CountryRegionSerializer to serialize related object(s).

like image 159
Willem Van Onsem Avatar answered Jan 23 '26 20:01

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!