中学英語811710 views
中学理科1630641 views
ヒストリア290598 views
英語613639 views
小学社会310485 views
世界の国564520 views
MathPython497343 views
小学理科719870 views
教育149510 views
LaTeX962153 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Q オブジェクトで複雑な検索条件を組み立てる

Django ORM の filter メソッドをチェーンすると AND 条件になりますが、OR 条件や NOT 条件を表現するには Q オブジェクトが必要です。Q を使うことで、SQL の WHERE 句に相当する複雑な条件を Python らしく組み立てられます。

Q オブジェクトの基本

Qdjango.db.models からインポートして使います。

from django.db.models import Q

# OR 条件: タイトルに「Python」または「Django」を含む記事
articles = Article.objects.filter(
    Q(title__contains='Python') | Q(title__contains='Django')
)

| が OR、& が AND、~ が NOT を表します。

演算子意味SQL の対応
|ORWHERE ... OR ...
&ANDWHERE ... AND ...
~NOTWHERE NOT ...

通常の filter チェーンは AND しか書けませんが、Q を使えば柔軟に条件を組み合わせられます。

OR 条件

「どちらかの条件に一致すればよい」場合は | で結合します。

# 下書きまたはカテゴリが「技術」の記事
articles = Article.objects.filter(
    Q(is_draft=True) | Q(category='技術')
)

生成される SQL は次のようになります。

SELECT * FROM article
WHERE is_draft = TRUE OR category = '技術';

NOT 条件

~ を付けると条件を反転できます。exclude で書ける場面もありますが、他の条件と組み合わせるときは ~Q の方が見通しがよくなります。

# カテゴリが「雑記」でなく、かつ公開済みの記事
articles = Article.objects.filter(
    ~Q(category='雑記') & Q(is_draft=False)
)

複数の条件を組み合わせる

Q オブジェクト同士はネストできるため、括弧で優先順位を制御しながら複雑な条件を表現できます。

# (タイトルに「Python」を含む OR カテゴリが「技術」)
# AND 公開済み
articles = Article.objects.filter(
    (Q(title__contains='Python') | Q(category='技術'))
    & Q(is_draft=False)
)

Python の演算子優先順位に従って評価されるため、&| よりも先に結合します。意図を明確にするためにも、括弧を明示的に付ける方が安全です。

Q と通常のキーワード引数を混在させる

filter の中で Q オブジェクトと通常のキーワード引数を一緒に使うことも可能です。ただし、Q オブジェクトを先に書くというルールがあります。

# Q オブジェクトが先、キーワード引数が後
articles = Article.objects.filter(
    Q(title__contains='Python') | Q(title__contains='Django'),
    is_draft=False
)

キーワード引数を Q より先に書くと SyntaxError になります。Python の仕様として、位置引数はキーワード引数の前に書かなければならないためです。

filter チェーン

AND 条件のみ。シンプルな条件なら十分

Q オブジェクト

OR・NOT を含む複雑な条件に対応。演算子で柔軟に組み立てられる

Q オブジェクトを動的に組み立てる

検索フォームなどでユーザーの入力に応じて条件を動的に追加したい場面では、Q オブジェクトをループで結合できます。

from functools import reduce
from operator import or_

keywords = ['Python', 'Django', 'Flask']
conditions = [Q(title__contains=kw) for kw in keywords]
combined = reduce(or_, conditions)

articles = Article.objects.filter(combined)

reduceor_ を使って、リスト内の Q オブジェクトをすべて OR で結合しています。and_ に変えれば AND 条件にもなります。

単純な AND 条件だけなら filter のチェーンで十分ですが、OR や NOT が絡む条件、あるいは動的に条件を組み立てる必要がある場面では Q オブジェクトが不可欠です。Django ORM を使いこなすうえで、確実に押さえておきたい機能と言えます。