我们假设我有以下模型:
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
。
答案 0 :(得分:9)
这不是一个查询,但它非常有效。这会对所涉及的每个表执行一次查询,并在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')
答案 1 :(得分:6)
我已经和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中的信息。
答案 2 :(得分:4)
select_related()
和prefetch_related()
是您的解决方案。他们的工作方式几乎相同,但有一些不同。
select_related()
通过创建SQL连接并在SELECT语句中包含相关对象的字段来工作。因此,select_related
获取相同数据库查询中的相关对象。但它只适用于一对一或一对多的关系。示例如下 -
entry = Entry.objects.select_related('blog').get(id=5)
or
entries = Entry.objects.filter(foo='bar').select_related('blog')
另一方面, prefetch_related()
对每个关系进行单独查找,并在Python中进行“加入”。这允许它预取多对多和多对一对象,这是使用select_related
无法完成的。因此prefetch_related
将仅为每个关系执行一个查询。示例如下 -
Pizza.objects.all().prefetch_related('toppings')
答案 3 :(得分:1)
在 Django 3.2 中,框架在使用方法 QuerySet.filter() 时会自动遵循关系
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
这将编译为以下 SQL 查询:
SELECT
"polls_choice"."id",
"polls_choice"."question_id",
"polls_choice"."choice_text",
"polls_choice"."votes"
FROM
"polls_choice"
INNER JOIN "polls_question" ON
("polls_choice"."question_id" = "polls_question"."id")
WHERE
"polls_question"."pub_date" BETWEEN 2020-12-31 23:00:00 AND 2021-12-31 22:59:59.999999
在此处查看教程:https://docs.djangoproject.com/en/3.2/intro/tutorial02/
答案 4 :(得分:-1)
来自django.db
导入连接在您的视图中包含以下声明:
cursor = connection.cursor()
cursor.execute("select * From Postion ON Position.name = Player.position JOIN
PlayerStats ON Player.name =
PlayerStats.player JOIN PositionStats ON Position.name = PositionStats.player")
solution = cursor.fetchall()