【Django】複数のQuerySetを一つのQuerySetにする方法

Djangoで作成したモデルをobjects.filter()メソッド等で抽出した場合、

‘django.db.models.query.QuerySet’型のオブジェクトが返されます。

このQuerySetはテンプレート内でもviews.pyの中でもリストの用にして扱うことができます。
別々の条件でQuerySetを生成したけれど、一つのQuerySetとしてまとめて扱いたいという場合に複数のQuerySetを一つのQuerySetに結合する方法を解説します。

結論から言うと、unionメソッドを使うことで複数のQuerySetを結合することができます。以下ではunionメソッドの使い方を解説していきます。

前提

今回はnameとpriceをフィールドにもつProductというモデルを利用していきます。

Productは既に5つ用意してあり、それぞれをProduct.objects.all()で取得した結果をテンプレートから出力した結果が以下のようになっています。

all_products = Product.objects.all()
</table>
<hr>
<h2>Queryset_2</h2>
<table border="1">
    <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
    {% for product in Queryset_2%}
    <tr>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>

union()で結合する

それではさっそくunionの使い方を説明していきます。

まずは結合する前のQuerySetが必要なので、Productモデルからpriceが300のものと500のものをそれぞれfilter()メソッドで抽出していきます。

それぞれをqueryset_1、queryset_2という変数に代入しておき、それらをunionでまとめたものをqueryset_3とします。

以下のコードで上記のことを行っています。

views.py

from django.shortcuts import render
from .models import Product
# Create your views here.
def result(request):
    all_products = Product.objects.all()
    queryset_1 = Product.objects.filter(price=300)
    queryset_2 = Product.objects.filter(price=500)
    queryset_3 = queryset_1.union(queryset_2)
    
    context = {
        'all_products': all_products,
        'queryset_1': queryset_1,
        'queryset_2': queryset_2,
        'queryset_3': queryset_3, 
    }
    
    return render(request, 'result.html', context)

result.html

<h2>全商品</h2>
<table border="1">
    <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
    {% for product in all_products%}
    <tr>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
<hr>
<h2>Queryset_1</h2>
<table border="1">
    <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
    {% for product in queryset_1%}
    <tr>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
<hr>
<h2>Queryset_2</h2>
<table border="1">
    <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
    {% for product in Queryset_2%}
    <tr>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
<hr>
<h2>Queryset_3(Queryset_1 + Queryset_2)</h2>
<table border="1">
    <thead>
        <tr>
            <th>name</th>
            <th>price</th>
        </tr>
    </thead>
    <tbody>
    {% for product in queryset_3%}
    <tr>
        <td>{{product.name}}</td>
        <td>{{product.price}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>

出力結果

まとめ

queryset_1.union(queryset_2)という構文で二つのQuerySetを一つにまとめることができます。

以下書籍を参考にしました。