这些是我的模特:
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
模型构建。
答案 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)
我们也可以简单地Result
和build
调用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)
现在你应该有一个包含每个案例字典的表格。将builds
和matrix
作为上下文传递给您的模板。然后,您可以遍历builds
以创建表标题(请注意在开头列出一两列的空格以列出案例)。然后迭代matrix
并创建表体。首先获取第一列(或前两列)的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
循环中,我们为每个case创建一个表行。在嵌套循环中,我们输出状态。
这是一种非常简单的方法,可能会进一步优化,但我留给你。