Как сделать правильный обратный запрос при использовании общих отношений Django? - PullRequest
0 голосов
/ 06 ноября 2018

Я реализовал общие отношения django для создания отношений между моделями. Мои модели

class CessPoint(BaseModel):
    ....
    title = models.CharField(max_length=100)

class BilledVehicle(BaseModel):
    ....
    source = models.ForeignKey(CessPoint, on_delete=models.CASCADE)

class Bill(BaseModel):
    .....
    content_type = models.ForeignKey(
    ContentType, on_delete=models.CASCADE, null=True)
    object_id = models.UUIDField(null=True)
    billed_item = GenericForeignKey()

class BillPayment(BaseModel):
    .....
    bill = models.ForeignKey(Bill, on_delete=models.CASCADE)        

Я хотел бы получить платежи за BilledVehicle. Вот как я бы хотел это сделать.

BillPayment.objects.filter(bill__content_type=ContentType.objects.get_for_model(BilledVehicle)).values('bill__billed_item__source__title').annotate(total_paid=Sum('amount_paid')).order_by('-total_paid')   

Я получаю ошибку:

Field 'billed_item' does not generate an automatic reverse relation and therefore cannot be used for reverse querying. If it is a GenericForeignKey, consider adding a GenericRelation.

Согласно этому ответу, Как пройти GenericForeignKey в Django? , определение GenericRelation может решить мою проблему. Но опять же, я не определил GenericRelation , потому что добавление одного будет каскадировать все отношения в соответствии с поведением по умолчанию

В отличие от ForeignKey, GenericForeignKey не принимает аргумент on_delete для настройки этого поведения; при желании вы можете избежать каскадного удаления, просто не используя GenericRelation, и альтернативное поведение может быть обеспечено с помощью сигнала pre_delete.

1 Ответ

0 голосов
/ 06 ноября 2018

Если вы не хотите создавать объект GenericRelation в вашем модуле BilledVehicle, django не сможет связать его напрямую с вашим Bill, используя значения.

Вы можете обойти это, используя словарь для хранения уникальных CessPoint заголовков и их total (делайте аннотации самостоятельно) из суммы BillPayment набора запросов, выплачиваемого следующим образом.

qs = BillPayment.objects.filter(
    bill__content_type=ContentType.objects.get_for_model(BilledVehicle))
ds = {}

for billPayment in qs:
    title = billPayment.billed_item.source.title
    ds[title] = ds.get(title, 0) + billPayment.amount_paid
...