使用Django通用关系时如何进行正确的反向查询?

时间:2018-11-06 06:48:50

标签: python django django-contenttypes

我已经实现了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.

根据此答案How to traverse a GenericForeignKey in Django?,定义 GenericRelation 可能会解决我的问题。但是再说一次,我没有定义 GenericRelation ,因为添加一个将按照默认行为层叠所有关系

  

与ForeignKey不同,GenericForeignKey不接受on_delete参数来自定义此行为;如果需要,可以通过不使用GenericRelation来避免级联删除,并且可以通过pre_delete信号提供替代行为。

1 个答案:

答案 0 :(得分:0)

如果您不想在BilledVehicle模块中创建GenericRelation对象,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
相关问题