Django combine 3 queryset

2024-05-12 20:53:21 发布

您现在位置:Python中文网/ 问答频道 /正文

好朋友,我不太熟悉把查询集合并成一个查询集。如何在不更改模板设计的情况下实现预期结果

注:我已经问过this question。我刚刚发现在Django中有一种组合多个查询集的方法。但这不是同一个问题

这是my views.py:

Markingbehaviors = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id')).values('Grading_Period').distinct('Grading_Period')\
        .order_by('Grading_Period')

Marking = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id'))

cores = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id')).values(
        'Marking__Marking',
        'Grading_Behavior__Grading_Behavior__Name',
        'Grading_Behavior__Grading_Behavior__GroupName').distinct(
        'Grading_Behavior__Grading_Behavior__Name') \
        .order_by('Grading_Behavior__Grading_Behavior__Name')

behaviors = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id')).values(
        'Marking__Marking',
        'Grading_Behavior__Grading_Behavior__Name',
        'Grading_Behavior__Grading_Behavior__GroupName').distinct(
        'Grading_Behavior__Grading_Behavior__GroupName') \
        .order_by('Grading_Behavior__Grading_Behavior__GroupName')

matches = cores.union(Marking,behaviors)

这是我的html:

<tr>
    {% for quarter in Markingbehaviors %}
        td class="tdquarter">Q {{quarter.Grading_Period}}</td>
    {% endfor %}
</tr>


{% for match in matches %}
    <tr>
       <td rowspan="2" colspan="4" class="tblcoretitle">{{match.Grading_Behavior__Grading_Behavior__Name}}</td>
    </tr>
    <tr>
       <td colspan="4" class="tblcore">{{match.Grading_Behavior__Grading_Behavior__GroupName}}</td>
       <td class="tblcore">{{match.Marking.Marking}}</td>
    </tr>
{% endfor %}

这是我对StudentsBehaviorGrades的管理员站点视图:

enter image description here

这是我目前的结果:

enter image description here

我想要结果:

enter image description here

更新

当我在my views.py中尝试此操作时:

matches = set(itertools.chain(cores, behaviors,Marking))

我收到了这个错误:

enter image description here

伴侣如果你有更好的解决方案或想法,请分享你的答案

这就是我渲染的方式

    Marking = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id'))\
        .order_by('Grading_Behavior__Grading_Behavior__Name')

    cores = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id')).values(
        'id',
        'Marking__Marking',
        'Grading_Period',
        'Grading_Behavior__Grading_Behavior__Name',
        'Grading_Behavior__Grading_Behavior__GroupName').distinct(
        'id',
        'Grading_Behavior__Grading_Behavior__Name').order_by(
        'id',
        'Grading_Behavior__Grading_Behavior__Name'
        )

    behaviors = StudentsBehaviorGrades.objects.filter(Teacher=teacher) \
        .filter(Students_Enrollment_Records__in=Students.values_list('id')).values(
        'id',
        'Marking__Marking',
        'Grading_Period',
        'Grading_Behavior__Grading_Behavior__Name',
        'Grading_Behavior__Grading_Behavior__GroupName').distinct(
        'id',
        'Grading_Behavior__Grading_Behavior__GroupName').order_by(
        'id',
        'Grading_Behavior__Grading_Behavior__GroupName'
    )

matches = cores.union(Marking,behaviors)

return render(request, 'Homepage/mystudentperreport.html',{ "matches":matches,})

Tags: nameinidobjectsfiltertdgradingvalues
3条回答

对于您的问题,有一个非常简单的解决方案,它不在queryset区域(某种程度上)

根据您告诉我们的情况,您正试图按照以下顺序对每个结果进行分组:

  1. 分级行为分级行为分组名称(组)
  2. 分级行为分级行为名称(名称)
  3. 评分周期(季度)

我认为queryset应该保持非常简单,然后您可以在模板中完成大部分工作

因此,首先,按照您想要的顺序获取所有标记,从组开始,并深入到细节(例如:核心->;名称->;季度)。据我所知,上面的三项清单应该很接近

然后在您的模板中,使用神奇的标记{% ifchanged %}(请参见docs),当表出现这种问题时,它会产生奇迹。但是,我会告诉你:模板可能很难阅读

无论如何,它应该是这样的:

<table>
<thead>
  {# Your table headings, quite static, with maybe a loop for quarters #}
</thead>
<tbody>
{% for match in matches %}
    {% ifchanged match.Grading_Behavior__Grading_Behavior__Name %}
        {#  We need a need row for each new name #}
        {% if not forloop.first %}
            {#  Close the previous one if not first loop #}
            </tr>
        {% endif %}
        <tr>
    {% endifchanged %}

    {# First, your group name  #}
    {% ifchanged match.Grading_Behavior__Grading_Behavior__GroupName %}
        <td rowspan="2" colspan="4" class="tblcoretitle">
            {{ match.Grading_Behavior__Grading_Behavior__GroupName }}
       </td>
    {% endif %}

    {# First, then the name  #}
    {% ifchanged match.Grading_Behavior__Grading_Behavior__Name %}
        <td colspan="4" class="tblcore">
            {{ match.Grading_Behavior__Grading_Behavior__Name }}
       </td>
    {% endif %}

    {# Then your marking #}
    <td class="tblcore">{{match.Marking.Marking}}</td>

    {% if forloop.last %}
        {# Close the last row in the last loop #}
        </tr>
    {% endif %}
{% endfor %}
</tbody>
</table>

这可能不太正确,但一旦您掌握了ifchange的窍门,并将重点放在它呈现的标记上,您就应该可以了

另外,不要忘记可以在{% for %}see docs中使用的变量

您希望matches对象具有如下形状的匹配列表:

matches = [{
        "core_value_name": "core_value_1",
        "behaviour_statements": [{
                "name": "behaviour_statement_1",
                "grades": {
                    "q1": "grade_q1",
                    "q2": "grade_q2",
                    "q3": "grade_q3",
                    "q4": "grade_q4"
                }
            },
            {
                "name": "behaviour_statement_2",
                "grades": {
                    "q1": "grade_q1",
                    "q2": "grade_q2",
                    "q3": "grade_q3",
                    "q4": "grade_q4"
                }
            },
            ...
        ]
    }, {
        "core_value_name": "core_value_2",
        "behaviour_statements": [{
                "name": "behaviour_statement_1",
                "grades": {
                    "q1": "grade_q1",
                    "q2": "grade_q2",
                    "q3": "grade_q3",
                    "q4": "grade_q4"
                }
            },
            ...
        ]
    }
    ...
]

然后,您可以对模板进行如下小调整:

{% for match in matches %} 
{% set first_row=True %} 
{% for behaviour_statement in match.behaviour_statements %} 
{% if first_row %}
<tr>
  <td rowspan="{% len(match.behaviour_statements) %}" colspan="4" class="tblcoretitle">{{match.core_value_name}}</td>
{% set first_row=False %} 
{% elif %}
<tr>
{% endif %}
  <td colspan="4" class="tblcore">{{behaviour_statement.name}}</td>
  <td class="tblcore">{{behaviour_statement.grades.q1}}</td>
  <td class="tblcore">{{behaviour_statement.grades.q2}}</td>
  <td class="tblcore">{{behaviour_statement.grades.q3}}</td>
  <td class="tblcore">{{behaviour_statement.grades.q4}}</td>
</tr>
{% endfor %} 
{% endfor %}

这会得到你想要的结果

组合查询集非常简单。在组合时有两个选项,如果它们是相同的,有时会表现得像

模型只是原始的SQL语句,SQL中的组合出现在python中的中。有Q对象用于更复杂的查找。让我看看

如果您有2个或更多查询集

您可以它们,如果它们属于同一类型

|相同,但是,您有不同的类型,这就是Q对象存在的原因

e、 g

from django.db.models import Q
my_concatenated_qs = Q(MyModel__my_attr_if_I_want="") & Q(MyAnotherModel)  

|也有效

注意:MyModel,MyAnotherModel不是一个模型实例,它只是名称,不是字符串。只是原始名称,没有引号

您还可以删除my_attr_if_I_want,我只是想说明在这里可以使用__语法

Q对象并不局限于我所展示的模型查询

e、 g

complex_queryset = MyModel.objects.filter(
    Q(my_attr__startswith='R') & ~Q(my_another_attr__startswith='Z')
    | Q(my_third_attr__startswith='R') & Q(my_fourth_attr__startswith='R')
)

您还可以否定查询集

e、 g

X = True
Y = not X

这是否定,用来否定Q对象(不是查询)

~Q(MyModel__startswith="A") | Q(MyModel__whatever__whatever=[])

此外,您还可以阅读关于Q对象here

相关问题 更多 >