Django ORM related_name, 역참조 삽질기 남긴다.. (피가 거꾸로 솟을뻔 했다)

 

 

아래와 같은 Model이 있다고 하자

차량(Car)이 있고 해당 차량에 적재할 수 있는 팔레트(Pallet)가 있다고 하자.

class Car(models.Model):
    car_number = models.CharField(max_length=50)
    type = models.CharField(max_length=50)

    def __str__(self):
        return f"{self.car_number}({self.type})_팔레트개수:{self.pallet.count()}"


class Pallet(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE, related_name='pallet')
    seq = models.PositiveIntegerField()

    def __str__(self):
        return f"{self.car}({self.seq})번째"
        
        
class OrderList(models.Model):
    codeName = models.CharField(max_length=255)
    pallet = models.ForeignKey(Pallet, on_delete=models.CASCADE, related_name='order_list', null=True, blank=True)

 

Car에서 자기에게 할당된 팔레트를 찾으려면 어떻게 하면 좋을까?

related_name을 활용한 역참조(reverse relation)를 쓰면된다.

Car.objects.first().pallet.all()

이런식으로 첫번째 차량의 모든 팔레트를 가져 오고 싶으면 여기서 pallet는 내가 related_name에서 pallet라고 명시해서 그렇다! love면 love로 참조하면 된다.

 

그렇다면 역참조 annotate는 어떻게 할까? 예를들어 모든 차량의 팔레트 수를 알고 싶을때 어떻게 할까?

Car.objects.all().annotate(pallet_count=Count(F('pallet')))

이런식으로 annotate를 쓰고 pallet로 참조해주면 된다.

 

 

이걸 쿼리로 풀면 아래와 같다. 진짜 간단한 쿼리다...

SELECT "release_car"."id", "release_car"."car_number", "release_car"."type", COUNT("release_pallet"."id") AS "pallet_count" FROM "release_car" LEFT OUTER JOIN "release_pallet" ON ("release_car"."id" = "release_pallet"."car_id") GROUP BY "release_car"."id"

 

 

마지막으로 역참조 filter + 역참조 annotate까지 붙이려면 어떻게 할까?

예를들면 해당 차량(car_id)의 모든 팔레트를 구하고싶은데 팔레트에 적재된 주문의 일자(주문 내역은 order_list로 역참조)로 filter하고 order_list 역참조의 주문 내역 Count를 알고싶을때는 아래와 같이 하면 된다.

 

상당히 복잡하게 말했는데 filter에서 order_list는 Pallet의 컬럼이 아니다 그런데 역참조로 인해서 컬럼처럼 쓰고있고(filter에서) annotate에서 또한 order_list를 마치 자신의 컬럼인양 사용하고 있다. 편하다 편해

pallets = Pallet.objects.filter(car__id=car_id).filter(order_list__ymd=ymd).annotate(counts=Count(F('order_list')))

 

 

결론 : 역참조는 좋다. 근데 헷갈린다.

'django' 카테고리의 다른 글

Django workers process 메모리 공유  (0) 2021.02.19
Django queryset to json  (0) 2019.12.31
Django Docker 배포(production)  (0) 2019.10.25
헷가리는 Django Static 간략 정리  (0) 2019.10.18
DRF ForeignKey Update  (0) 2019.06.14

+ Recent posts