Django Query Set将Row值作为列名

时间:2018-01-29 16:40:56

标签: python django django-models django-views

这些是我的模特:

short?

我需要一个django class Build(models.Model): name = models.CharField(db_index=True, max_length=56) description = models.TextField(max_length=512, null=True, blank=True) class Case(models.Model): name = models.CharField(db_index=True, max_length=255) description = models.TextField(max_length=1024, null=True, blank=True) class Result(models.Model): status = models.CharField(max_length=12) result_build = models.ForeignKey(Build, related_name='result_build', on_delete=models.CASCADE) result_case = models.ForeignKey(Case, related_name='result_case', on_delete=models.CASCADE) 来获取如下数据:

QuerySet

其中.................................................... : case_name : case_description : build_X : build_Y : :...........:..................:.........:.........: : test1 : case1 : PASS : FAIL : : test2 : case2 : FAIL : PASS : :...........:..................:.........:.........: case_name是来自case_description模型的字段。

build_X和build_Y是Case模型中可用的两个构建名称 和PASS和FAIL是不同案例的状态,并从Build模型构建。

1 个答案:

答案 0 :(得分:1)

这是与直通模型的多对多关系的经典案例。模型类可以重构如下:

class Build(models.Model):
    name = models.CharField(db_index=True, max_length=56)
    description = models.TextField(max_length=512, null=True, blank=True)


class Case(models.Model):
    name = models.CharField(db_index=True, max_length=255)
    description = models.TextField(max_length=1024, null=True, blank=True)
    builds = models.ManyToManyField('Build', through='Result', related_name='cases')


class Result(models.Model):
    status = models.CharField(max_length=12)
    build = models.ForeignKey('Build', on_delete=models.CASCADE)
    case = models.ForeignKey('Case', on_delete=models.CASCADE)

我们也可以简单地Resultbuild调用case的属性,而名称中不会有冗余。虽然related_name并不麻烦,但我们并不需要它。

现在您可以使用m2m关系查询模型:

case = Case.objects.get(pk=1) # get Case object with primary key 1
case.builds.all() # get all Build objects related to case
build = Build.objects.get(pk=1) # get Build object with primary key 1
build.cases.all() # get all Case objects related to build
# UPDATE
# get Result objects for the "case" with pk=1 retrieved before
results = Result.objects.filter(case=case)
# output each entry as row with all property values
for r in results:
    print(r.case.name, r.case.description, r.build.name, r.build, description, r.status)

您还可以使用.filter缩小查询结果范围。

编辑:

这是创建矩阵表的一种可能方法。这是您可以放在视图中的代码:

cases = Case.objects.all()
builds = Build.objects.all()
matrix = []
for c in cases:
    result = {}
    result['case'] = c
    result['status'] = []
    for b in builds:
        result['status'].append(Result.objects.filter(
                                    case=c,
                                    build=b
                               ).values_list('status', flat=True))
    matrix.append(result)

现在你应该有一个包含每个案例字典的表格。将buildsmatrix作为上下文传递给您的模板。然后,您可以遍历builds以创建表标题(请注意在开头列出一两列的空格以列出案例)。然后迭代matrix并创建表体。首先获取第一列(或前两列)的case,然后输出status

我希望这可以指明你的方式。一旦获得了正确的结果,您就可以进一步优化性能。

编辑2:

以下是表格的示例。
将上面的代码段中的buildsmatrix作为上下文传递给模板:

<table>
  <tr>
    <th>Case name</th>
    <th>Case description</th>
    {% for b in builds %}
      <th>{{ b.name }}</th>
    {% endfor %}
  </tr>
  {% for row in matrix %}
    <tr>
      <td>{{ row.case.name }}</td>
      <td>{{ row.case.description }}</td>
      {% for s in row.status %}
        <td>{{ s.0 }}</td>
      {% endfor %}
    </tr>
  {% endfor %}
</table>

在第一个for循环中,我们创建一个表头,其中包含两个列标题,用于案例名称和案例描述以及每个构建的一个列标题。
在第二个for循环中,我们为每个case创建一个表行。在嵌套循环中,我们输出状态。

这是一种非常简单的方法,可能会进一步优化,但我留给你。