简体   繁体   English

Django结合3个查询集

[英]Django combine 3 queryset

Good day mates, I am not very familiar with combining querysets into one.朋友们好,我不太熟悉将查询集合并为一个。 How do I achieve my desired result without changing the template design?如何在不改变模板设计的情况下达到我想要的结果?

Note: I have already asked this question .注意:我已经问过这个问题了 I just found out that there is such a thing as combining multiple querysets in Django.我刚刚发现在 Django 中有组合多个查询集这样的事情。 It is not the same question though.不过,这不是同一个问题。

This is my views.py:这是我的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)

This is my html:这是我的 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 %}

This is my adminsite view of StudentsBehaviorGrades :这是我的StudentsBehaviorGrades管理站点视图:

在此处输入图片说明

This is my current result:这是我目前的结果:

在此处输入图片说明

I want result:我想要结果:

在此处输入图片说明

Update更新

When I tried this in my views.py:当我在我的 views.py 中尝试这个时:

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

I received this error:我收到此错误:

在此处输入图片说明

mate if you have a better solution or idea please share your answer.伙计,如果您有更好的解决方案或想法,请分享您的答案。

This is how i render这就是我渲染的方式

    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,})

Combining querysets is very straight forward.组合查询集非常简单。 You have two options when combining which SOMTIMES act like if they're the same.在组合SOMTIMES时,如果它们相同,您有两个选择。

Models deeply are just raw SQL statements, Combinations in SQL happen with AND or OR , Which exist in python.模型深深的只是原始的SQL语句,在组合与SQL发生OR,在蟒蛇而存在。 There're Q objects for more complex look ups.Q对象用于更复杂的查找。 Let's see.让我们来看看。

If you have 2 querysets or more.如果您有 2 个或更多查询集。

You can OR or AND them, qs_3 = qs_1 & qs_2 will return both of them concatenated IF THEY ARE OF THE SAME TYPE您可以ORAND它们, qs_3 = qs_1 & qs_2它们qs_3 = qs_1 & qs_2同一类型qs_3 = qs_1 & qs_2将返回它们连接在一起

Same with ||相同, However, you have different types, That's why Q objects exist. , 但是,您有不同的类型,这就是Q对象存在的原因。

eg例如

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

| works too.也有效。

NOTE: MyModel, MyAnotherModel is not a model instance, It's just the name, not a string too.注意: MyModel、MyAnotherModel 不是模型实例,它只是名称,也不是字符串。 Just the raw name without quotes.只是没有引号的原始名称。

You can also remove the my_attr_if_I_want , I just wanted to show it's possible to use the __ syntax here.您还可以删除my_attr_if_I_want ,我只是想表明可以在这里使用__语法。

Q objects are not limited to model queries like I've shown Q对象不仅限于我展示的模型查询

eg例如

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')
)

You can also negate querysets您还可以否定查询集

eg例如

X = True
Y = not X

This is Negation , To negate Q objects (NOT query)这是Negation ,否定 Q 对象(不是查询)

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

Further more, You can read about Q objects here此外,您可以在此处阅读有关 Q 对象的信息

You want your matches object to a list of matches with a shape like the following:您希望将匹配对象指向具有如下形状的匹配列表:

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"
                }
            },
            ...
        ]
    }
    ...
]

Then you can use your template with a minor tweak like so:然后你可以使用你的模板做一个小的调整,如下所示:

{% 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 %}

This gets you your desired result.这会让你得到你想要的结果。

There is quite a simple solution for your problem, and it's not in the queryset area (kind of).您的问题有一个非常简单的解决方案,它不在查询集区域(有点)。

From what you have told us, you are trying to group every result by, in order:根据您告诉我们的内容,您正在尝试按以下顺序对每个结果进行分组:

  1. Grading_Behavior__Grading_Behavior__GroupName (group) Grading_Behavior__Grading_Behavior__GroupName(组)
  2. Grading_Behavior__Grading_Behavior__Name (name) Grading_Behavior__Grading_Behavior__Name(姓名)
  3. Grading_Period (quarter) Grading_Period(季度)

I think the queryset should remain very simple, and then you can do the huge part in your template.我认为查询集应该保持非常简单,然后您可以在模板中完成大部分工作。

So first things first, get all your marking with the order you want, beginning with groups and going more into detail (eg: core -> name -> quarter).因此,首先,按照您想要的顺序进行所有标记,从组开始并更详细地进行(例如:核心 -> 名称 -> 季度)。 From what I've understood, the 3-item list above should be quite close.据我了解,上面的 3 项列表应该非常接近。

Then in your template, use the magic tag {% ifchanged %} (see docs ), it does wonders when having this kind of problem with tables.然后在您的模板中,使用魔术标签{% ifchanged %} (请参阅文档),当表格出现此类问题时,它确实很奇怪。 But, I will give you that: the template may be quite hard to read.但是,我会告诉你:模板可能很难阅读。

Anyway, it should look like this:无论如何,它应该是这样的:

<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>

It may not be quite right, but once you get the hang of ifchanged, and you focus on the markup that it renders, you should be ok.这可能不太正确,但是一旦你掌握了 ifchanged 的​​窍门,并且你专注于它呈现的标记,你应该没问题。

Also don't forget the variables you can use in a {% for %} , see docs另外不要忘记您可以在{% for %}使用的变量, 请参阅文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM