私は次のモデルを持っていると仮定しましょう:
class Position(models.Model):
name = models.CharField()
class PositionStats(models.Model):
position = models.ForeignKey(Position)
averageYards = models.CharField()
averageCatches = models.CharField()
class PlayerStats(models.Model):
player = models.ForeignKey(Player)
averageYards = models.CharField()
averageCatches = models.CharField()
class Player(models.Model):
name = models.CharField()
position = models.ForeignKey(Position)
DjangoのORMを使用して同等のSQLクエリを実行したい:
SELECT *
FROM PlayerStats
JOIN Player ON player
JOIN PositionStats ON PositionStats.position = Player.position
DjangoのORMでこれを行うにはどうすればよいですか?クエリは正確ではありませんが、アイデアは、DjangoのORMを使用して、プレーヤーの位置に基づいてPlayerStats
と結合されたPositionStats
を提供する単一のクエリが欲しいということです。
1つのクエリではありませんが、非常に効率的です。これは、関係する各テーブルに対して1つのクエリを実行し、それらをPythonで結合します。 prefetch_related
の詳細: https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related
Player.objects.filter(name="Bob").prefetch_related(
'position__positionstats_set', 'playerstats_set')
私はDjangoでしばらく働いていて、テーブルの結合を理解するのにかなり苦労しましたが、私は最終的に理解し、他の人に伝えたいと思います彼らは私がそれで持っていた欲求不満を避けるかもしれません。
次のmodel.pyを検討してください。
class EventsMeetinglocation(models.Model):
id = models.IntegerField(primary_key=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=200)
class Meta:
managed = True
db_table = 'events_meetinglocation'
class EventsBoardmeeting(models.Model):
id = models.IntegerField(primary_key=True)
date = models.DateTimeField()
agenda_id = models.IntegerField(blank=True, null=True)
location_id = models.ForeignKey(EventsMeetinglocation)
minutes_id = models.IntegerField(blank=True, null=True)
class Meta:
managed = True
db_table = 'events_boardmeeting'
ここで、EventsBoardmeetingのlocation_idはEventsMeetinglocationのidの外部キーであることがわかります。これは、EventsBoardmeetingを経由してEventsMeetinglocationの情報を照会できることを意味します。
ここで、次のviews.pyを検討してください。
def meetings(request):
meetingData = EventsBoardmeeting.objects.all()
return render(request, 'board/meetings.html', {'data': meetingData })
他の投稿で何度も述べたように、Djangoは自動的に結合を処理します。EventsBoardmeetingですべてを照会すると、外部キーでも関連情報を取得しますが、アクセス方法はこれはhtmlの場合とは少し異なり、その結合に関連する情報にアクセスするには、外部キーとして使用される変数を調べる必要があります。
{% for x in data %}
{{ x.location_id.name }}
{% endfor %}
上記は、外部キーの結合の結果であるテーブル内のすべての名前を参照しています。 xは本質的にEventsBoardmeetingテーブルであるため、x.location_idにアクセスするとき、EventsMeetinglocationの情報にアクセスできる外部キーにアクセスします。
select_related()
およびprefetch_related()
がソリューションです。ほぼ同じように機能しますが、いくつかの違いがあります。
select_related()
は、SQL結合を作成し、関連するオブジェクトのフィールドをSELECTステートメントに含めることで機能します。このため、_select_related
_は同じデータベースクエリで関連オブジェクトを取得します。ただし、1対1または1対多の関係でのみ機能します。例は以下です-
_entry = Entry.objects.select_related('blog').get(id=5)
or
entries = Entry.objects.filter(foo='bar').select_related('blog')
_
一方、prefetch_related()
は、各関係に対して個別のルックアップを実行し、Pythonで「結合」を実行します。これにより、多対多および多対1オブジェクトをプリフェッチできます。これは_select_related
_を使用して実行することはできません。したがって、_prefetch_related
_は各リレーションに対して1つのクエリのみを実行します。以下に例を示します
_Pizza.objects.all().prefetch_related('toppings')
_