这些是我的模型:
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)
我需要一个 django QuerySet
来获取如下数据:
....................................................
: case_name : case_description : build_X : build_Y :
:...........:..................:.........:.........:
: test1 : case1 : PASS : FAIL :
: test2 : case2 : FAIL : PASS :
:...........:..................:.........:.........:
其中 case_name
和 case_description
是 Case
模型中的字段。
build_X 和 build_Y 是 Build
模型中可用的两个构建名称
PASS 和 FAIL 是不同案例的状态,并根据 Result
模型构建。
最佳答案
这是使用直通模型进行多对多关系的经典案例。模型类可以重构如下:
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)
我们还可以简单地调用 Result
的属性 build
和 case
,而无需名称冗余。尽管 lated_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
来缩小查询结果范围。
编辑:
这是创建矩阵表的一种可能方法。这是您可以放入 View 中的代码:
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)
现在您应该有一个包含每种情况的字典的表。将 builds
和 matrix
作为上下文传递给模板。然后,您可以迭代 builds
以创建表标题(请注意在开头留出一两列空间以列出案例)。然后迭代矩阵
并创建表体。首先获取第一列(或前两列)的 case
,然后输出 status
。
我希望这能为您指明方向。一旦获得正确的结果,您就可以进一步优化性能。
编辑2:
这是表格的示例。
将上面代码片段中的 builds
和 matrix
作为上下文传递给模板:
<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 循环中,我们为每种情况创建一个表行。在嵌套循环中,我们输出状态。
这是一种非常简单的方法,可能可以进一步优化,但我将其留给您。
关于python - Django 查询集获取行值作为列名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48506031/