Django: Сериализаторы и запросы "один ко многим" и "многие к одному
У меня есть отношения, подобные этим: Один город имеет один ко многим зданиям; одно здание имеет ноль ко многим устройствам.
Пользователь должен иметь возможность запросить город по его PK, получив в ответ город, здания в городе и устройства в этих зданиях.
Я знаю, что внешние ключи необходимы при создании моделей, например, так:
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
У меня проблемы с тем, как написать сериализаторы и запросы. На данный момент мои сериализаторы включают только поля, соответствующие столбцам этой таблицы:
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', ...]
Однако, когда мне нужно ответить на GET-запрос о городе, я знаю только, как использовать вложенные циклы for для получения данных о здании и устройстве после нахождения города по введенному ID. Я предполагаю, что есть лучший способ, но мне трудно найти четкие ответы в Интернете.
Используйте ключевое слово related_name в ваших моделях, вы можете узнать больше об этом - вот как это работает -
Определите свои модели и добавьте related_name к внешним ключам как -
.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')
Затем определите ваши сериализаторы в обратном порядке и добавьте related_name моделей в поле ваших сериализаторов--
.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' ...]
Теперь, когда вы попытаетесь получить город, вы получите все здания, относящиеся к этому городу, а также все устройства, связанные с каждым зданием.
Существует еще один метод, называемый serializermethodfield, он очень полезен во многих областях, вы можете использовать любой из них в зависимости от вашего выбора.
Надеюсь, это поможет.