具有键/值表结构的Django ORM

时间:2018-03-17 04:00:48

标签: django orm django-orm

我试图让django orm在数据库中复制一个针对我当前表结构的调用:

表:

ServiceItems {Id,name,user,date_created}

ServiceItemsProps {fk_to_ServiceItems Item_id,Id,key,value}

我尝试使用ServiceItemsProps表中的多个键作为列从ServiceItem表中选择项目。

我可以通过以下查询完成此操作:

> select tbl1.value as bouncebacks, tbl2.value as assignees from
> service_items join service_item_props as tbl1 on tbl1.item_id =
> service_items.id join service_item_props as tbl2 on tbl2.item_id =
> service_items.id where service_items.item_type='CARD' and
> tbl1.key='bouncebacks' and tbl2.key='assignees'

但是我无法弄清楚如何在Django的ORM中重现这一点。我不想在这里的语句中注入原始SQL,因为代码库的可移植性非常重要。

models.py

部分
class ServiceItems(models.Model):

    class Meta:
        db_table = 'service_items'
        unique_together = ('service', 'item_type', 'item_id')

    service = models.ForeignKey(Service, blank=False, db_column='service_id', on_delete=models.CASCADE)
    item_type = models.CharField(max_length=255, blank=False)
    url = models.TextField(blank=True, null=True)
    item_id = models.TextField(blank=True, null=True)
    item_creation_user = models.TextField(blank=True, null=True)
    item_creation_date = models.DateTimeField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

class ServiceItemProps(models.Model):

    class Meta:
        db_table = 'service_item_props'

    item = models.ForeignKey(ServiceItems, blank=False, db_column='item_id', on_delete=models.CASCADE)
    prop_id = models.TextField(blank=True, null=True)
    key = models.CharField(max_length=255, blank=False)
    value = models.TextField(blank=True, null=True)

1 个答案:

答案 0 :(得分:1)

# change one line to make it easier to query
item = models.ForeignKey(ServiceItems, blank=False, db_column='item_id', on_delete=models.CASCADE, related_name='item_props')

查询应该变为:

ServiceItem.objects.filter(Q(item_type='CARD') & (Q(item_props__key='bouncebacks') | Q(item_props__key='assignees'))

=============================================== ===============

我想我误解了你的问题。

我相信这是一个使用.raw()的好例子。

试试这个:

qs = ServiceItemProps.objects.raw('''
SELECT sip1.*, sip2.value as other_value
FROM {item_table} as service_items
    INNER JOIN {props_table} as sip1 on sip1.item_id = service_items.id
    INNER JOIN {props_table} as sip2 on sip2.item_id = service_items.id
WHERE service_items.item_type='CARD' and sip1.key='bouncebacks' and sip2.key='assignees'
'''.format(item_table=ServiceItems._meta.db_table, props_table=ServiceItemProps._meta.db_table)


for itemprop in qs:
    print(qs.value, qs.other_value)