Home > OS >  Django: One-to-Many and Many-to-One Serializers and Queries
Django: One-to-Many and Many-to-One Serializers and Queries

Time:12-04

I have a relationship similar to this: One city has one-to-many buildings; one building has zero-to-many devices.

The user must be able to request a city by its PK, receiving in response the city, the buildings in the city, and the devices in those buildings.

I know that foreign keys are necessary in creating the models, like this:

class City(models.Model):
    #Columns here

class Building(models.Model):
    cityId = models.ForeignKey(City, on_delete=models.CASCADE)
    #Columns here

class Device(models.Model):
    buildingId = models.ForeignKey(Building, on_delete=models.CASCADE)
    #Columns here

What I'm having trouble with is how to write the serializers and the queries. As of now, my serializers only include fields corresponding to that table's columns:

class CitySerializer(serializers.ModelSerializer):
    class Meta:
        model = City
        fields = ['id', ...]

class BuildingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Building
        fields = ['id', 'cityId', ...]

class DeviceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Device
        fields = ['id', 'buildingId', ...]

However, when I have to respond to a GET request for the city, I only know how to use a nested for loops to get the building and device data after finding the city by the inputted ID. I presume there's a better way, but I'm having trouble finding clear answers online.

CodePudding user response:

Use related_name keyword in your models, you can learn more about it -- here is how it works--

  1. Define you models and add related_name to the foreign keys as -

    class City(models.Model):
         ##fields
    
     class Building(models.Model):
         cityId = models.ForeignKey(City, on_delete=models.CASCADE,related_name='abc')
    
     class Device(models.Model):
         buildingId = models.ForeignKey(Building, on_delete=models.CASCADE, related_name='xyz')
    
  2. Then define your serializers in reverse order and add the related_name of models in your serializers field--

     class DeviceSerializer(serializers.ModelSerializer):
         class Meta:
             model = Device
             fields = ['id', 'buildingId', ...]
    
     class BuildingSerializer(serializers.ModelSerializer):
         xyz = DeviceSerializer(many=True, read_only=True)
         class Meta:
             model = Building
             fields = ['id', 'cityId', xyz ...]
    
     class CitySerializer(serializers.ModelSerializer):
         abc = BuildingSerializer(many=True, read_only=True)
         class Meta:
             model = City
             fields = ['id', 'abc' ...]
    

Now when you will try to get the city, you will get all the building rel;ated to that city and also all the Devices related to each building.

There is one another method called as serializermethodfield, this is of great use in many areas, you can use any one depending upon your choice.

Hope this helps..

  • Related