【问题标题】:Django ORM with Key/Value Table structure具有键/值表结构的 Django ORM
【发布时间】:2018-08-26 04:57:44
【问题描述】:

我正在尝试让 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)

【问题讨论】:

  • 可以添加models.py吗?
  • @JerinPeterGeorge 我已经从文件中添加了字段定义

标签: django orm django-orm


【解决方案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)

【讨论】:

  • 哦,你需要from django.db.models import Q,文档在这里:docs.djangoproject.com/en/2.0/topics/db/queries/…
  • 这确实为我省去了很多麻烦,但它仍然没有返回这些键的值。
  • 可能我这里的要求没完全看懂,试试这个print(ServiceItem.objects.filter(Q(item_type='CARD') & (Q(item_props__key='bouncebacks') | Q(item_props__key='assignees')).query)打印后面的sql看看逻辑错在哪里
  • 过滤到属性与查询匹配的 ServiceItems,我想要的是每个 ServiceItem 的单行,其中还包含多个 ServiceItemProps 的值
  • 我相信这是使用原始查询的情况,请检查更新后的答案。
猜你喜欢
  • 2012-06-01
  • 2020-01-06
  • 2018-10-21
  • 2017-12-22
  • 1970-01-01
  • 2012-09-13
  • 2019-08-03
  • 2022-01-22
  • 1970-01-01
相关资源
最近更新 更多