Django объединить 3 запроса - PullRequest
       0

Django объединить 3 запроса

6 голосов
/ 26 февраля 2020

Добрый день, приятели, я не очень знаком с объединением наборов запросов в один. Как добиться желаемого результата без изменения дизайна шаблона?

Примечание: я уже задавал этот вопрос . Я только что узнал, что есть такая вещь, как объединение нескольких наборов запросов в Django. Это не тот же вопрос.

Это мой 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 %}

Это мой админсайт Студенты Поведенческие классы :

enter image description here

Это мой текущий результат:

enter image description here

Я хочу результат:

enter image description here

Обновление

Когда я попробовал это в моих 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,})

Ответы [ 3 ]

8 голосов
/ 25 марта 2020

Объединение наборов запросов очень просто. При объединении у вас есть два варианта, которые SOMTIMES действуют так же, как если бы они были одинаковыми.

Глубоко модели являются просто необработанными SQL операторами, комбинации в SQL происходит с И или ИЛИ , которые существуют в python. Есть Q объекты для более сложных поисков. Посмотрим.

Если у вас 2 набора запросов или более.

Вы можете ИЛИ или И их, qs_3 = qs_1 & qs_2 вернет оба из них сцепленных ЕСЛИ ОНИ ОДНОВРЕМЕННОГО ТИПА

То же самое с |, однако у вас есть разные типы, поэтому существует Q объектов.

например

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 объекты не ограничиваются модельными запросами, как я показал

например

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

Вы также можете отрицать наборов запросов

например

X = True
Y = not X

Это Отрицание , для отрицания объектов Q (НЕ запрос)

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

Более подробно, вы можете прочитать о объектах Q здесь

2 голосов
/ 25 марта 2020

Вы хотите, чтобы ваш объект совпадений представлял собой список совпадений с формой, подобной следующей:

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

Это дает вам желаемый результат.

0 голосов
/ 24 апреля 2020

Существует довольно простое решение для вашей проблемы, и оно не находится в области набора запросов (типа).

Исходя из того, что вы нам сказали, вы пытаетесь сгруппировать каждый результат по порядку:

  1. Grading_Behavior__Grading_Behavior__GroupName (group)
  2. Grading_Behavior__Grading_Behavior__Name (name)
  3. Grading_Period (квартал)
, по-моему, просто 1013 * * * * , а затем вы можете сделать огромную роль в вашем шаблоне.

Итак, во-первых, соберите все пометки в нужном вам порядке, начиная с групп и углубляясь в детали (например: core -> name - > четверть). Из того, что я понял, список из 3 пунктов выше должен быть довольно близок.

Затем в вашем шаблоне используйте тег magi c {% 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>

Возможно, это не совсем правильно, но как только вы получите возможность измениться, и вы сосредоточитесь на разметке, которую он отображает, у вас должно быть все в порядке.

Также не забывайте переменные, которые вы можете использовать в {% for %}, см. документы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...