Фон
Допустим, у меня есть такая структура:
models.py
class Location(models.Model):
pass
class Service(models.Model):
location = models.ForeignKey(Location, related_name="services",on_delete=models.CASCADE)
class Staff(models.Model):
service = models.ForeignKey(Service, related_name="staffs",on_delete=models.CASCADE)
class Performance(models.Model):
content = models.CharField("content", max_lenght=50)
staff=models.ForeignKey(Staff, related_name="performances",on_delete=models.CASCADE)
@property
def location(self):
return self.staff.service.location
Я хочу предоставить свои данные через API отдыха.
serializers.py
class StaffSerializer(serializers.ModelSerializer):
class Meta:
model = Staff
fields = ['id', 'service']
class ServiceSerializer(serializers.ModelSerializer):
staffs = StaffSerializer(many=True)
class Meta:
model = Service
fields = ['id', 'staffs']
class LocationSerializer(serializers.ModelSerializer):
services = ServiceSerializer(many=True)
class Meta:
model = Location
fields = ['id',]
Структура данных
Итак ... сериализованный Location
экземпляр будет выглядеть следующим образом:
{
"id":"some_location_id",
"services":[
{
"id":"some_service",
"staffs":[
{"id":"some_staff_id"},
{"id":"some_other_staff_id"}
]
} // ... Repeated for eah services
]
}
Теперь для по какой-то причине мне нужно раскрыть Performance
данные по схеме, которая выглядит следующим образом:
{
"id":"some_perfomance_id",
"content":"Foo",
"location":{
"id":"performance_staff__service__location_id",
"services":[
{
"id":"performance_staff__service_id",
"staffs":[
{"id":"performance_staff_id"} // ... Only one staff!
]
} // ... Only one service!
]
}
}
Исследуемые решения
Мне удалось заставить эту работу настраивать serializers
и передавать данные через некоторые личные атрибуты, но я ожидаю действительно странного поведения.
Мне нужен способ сделать это, используя Prefetch
Manager.py
Сосредоточив внимание только на services
, я бы ожидал что-то вроде этого:
class PerformanceManager(models.Manager):
def get_queryset(self):
service_qs = SubQuery(
Service.objects.filter(staffs=OuteRef("staff_id")).only("pk")
)
return super().get_queryset().prefetch_related(
Prefetch(
'staff__service__location__services',
queryset = Services.objects.filter(pk__in=service_qs)
)
)
Похоже, Prefetch
, SubQuery
и OuterRef
не очень хорошо играют вместе, и это делает смысл ... Для одного location
экземпляра я хочу настроить несколько предварительно выбранных services
, в зависимости от того, к какому performance
я обращаюсь к местоположению ...
Опросить Ион
Есть ли какой-нибудь pythonic
способ добиться этого?