如何使用Django ORM连接外键字段上的两个表?

2024-09-27 07:26:42 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有以下模型:

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的查询,它根据播放器的位置给我PlayerStatsPositionStats连接。


Tags: djangonamemodelmodelsormpositionclassplayer
3条回答

我已经和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\u id是EventsMeetinglocation中id的外键。这意味着我们应该能够通过EventsBoardmeeting查询EventsMeetinglocation中的信息。

现在考虑以下views.py:

def meetings(request):
    meetingData = EventsBoardmeeting.objects.all()
    return render(request, 'board/meetings.html', {'data': meetingData })

正如5月份其他帖子中多次提到的,django会自动处理连接。当我们在EventsBoardmeeting中查询所有内容时,我们也可以通过外键获得任何相关信息,但是在html中访问这些信息的方式有点不同。我们必须遍历用作外键的变量,才能访问与该联接关联的信息。例如:

{% for x in data %}
   {{ x.location_id.name }}
{% endfor %}

上面引用了表中的所有名称,这些名称是外键联接的结果。x本质上是EventsBoardmeeting表,所以当我们访问x.location_id时,我们访问的是外键,它使我们能够访问EventsMeetinglocation中的信息。

它不是一个查询,但非常有效。这将对涉及的每个表执行一个查询,并用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')

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

相关问题 更多 >

    热门问题