【问题标题】:How do I query on two incoming models using the Django ORM?如何使用 Django ORM 查询两个传入模型?
【发布时间】:2013-11-12 21:41:07
【问题描述】:

我有以下型号:

class DataStream(models.Model):
    category = models.CharField(max_length=255)
    description = models.TextField()

class DataStreamSubCategory(models.Model):
    data_stream = models.ForeignKey(DataStream)
    sub_category = models.CharField(max_length=255)

class DataStreamExample(models.Model):
    data_stream = models.ForeignKey(DataStream)
    example = models.CharField(max_length=255)

因此,每个 DataStream 可以有 0 个或多个 DataStreamSubCategory 对象和 0 个或多个 DataStreamExample 对象。

我想要做的基本上是在模板中的一个简单表格中显示这些值:

----------------------------------------
| Category | Sub-categories | Examples |
----------------------------------------
| Cat1     | Sub-cat1       | Ex1      |
|          | Sub-cat2       | Ex2      |
|          | Sub-cat3       |          |
----------------------------------------
| Cat2     | Sub-cat4       | Ex1      |
|          |                | Ex2      |
----------------------------------------

那么查询数据库以获取这些数据的最佳方法是什么?最明显(但可能很愚蠢)的方法是这样做:

data_streams = DataStream.objects.all()
for data_stream in data_streams:
    sub_categories = DataStreamSubCategory.objects.filter(data_stream=data_stream)
    examples = DataStreamExample.objects.filter(data_stream=data_stream)

但是有没有更有效的方法?似乎这里应该有一些 SQL 连接,但我不确定如何使用 Django ORM 来完成此操作。

【问题讨论】:

    标签: python django django-models django-templates django-queryset


    【解决方案1】:

    你可以像这样在模板中直接查询:

    <table>
    {% for ds in data_streams %}
       <tr>
          <td>
              {% ds.category %}
          </td>
          <td>
              {% for subcat in ds.datastreamsubsategory_set.all %}
                   {{subcat.sub_category}}
              {% endfor %}
          </td>
          <td>
              {% for example in ds.datastreamexample_set.all %}
                   {{example.example}}
              {% endfor %}
          </td>
    {% empty %}
       <tr><td colspan="3">No categories found</td></tr>
    {% endfor %}
    </table>
    

    我会让你自己弄清楚格式。

    在上下文中,只需发送{'data_streams': data_streams}

    基本上,对于反向外键关系,您会使用object.lowercasemodelname_set.all() 来获取相关对象查询集。

    阅读更多lookups that span relationships here

    或者你可以添加一个related_name 属性并使用它来代替lowercasemodelname_set

    如果您想减少数据库上的查询数量,您甚至可以考虑prefetch_related option

    【讨论】:

    • 太棒了!我知道必须有一个简单的内置机制来处理这个问题。
    • 所以你的例子不太好用,但很接近。您需要在模板中的模型名称末尾添加_set。所以,ds.datastreamsubsategory_set.all。谢谢!
    • @Geoff 你是对的。我正在考虑指定一个相关名称,但错过了这一点。谢谢 。我编辑了答案
    • 对于这种具有直接外键关系的情况,我建议使用select_related 而不是prefetch_related
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 2015-10-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    相关资源
    最近更新 更多