使用自联接将SQL查询转换为Django ORM

时间:2018-06-13 20:49:04

标签: python mysql django orm django-orm

我想在{player_id:1,first_value:2,last_value:3}这样的单个响应中获取具有玩家ID和其player_attribute值(多个)的玩家列表,我可以复制这个在Flask和peewee / sqlalchemy但是无法用Django解决这个问题。

我有这样的查询:

SELECT DISTINCT p.player_id, fn.value, ln.value
FROM player p
INNER JOIN player_attributes fn ON fn.player_id=p.player_id
AND fn.attribute_id=123
and fn.end_time is NULL
INNER JOIN player_attributes ln ON ln.player_id=p.player_id
AND ln.attribute_id=456
and ln.end_time is NULL
WHERE p.player_type_id = 789
ORDER BY ln.value, fn.value

使用模型:

class PlayerAttributes(models.Model):
    player_attribute_id = models.AutoField(primary_key=True)

    value = models.CharField(max_length=255, blank=True, null=True)
    end_date = models.IntegerField(blank=True, null=True)
    player = models.ForeignKey(
        player,
        models.DO_NOTHING,
        related_name="player_attributes"
    )
    attribute = models.ForeignKey(
        Attribute,
        models.DO_NOTHING,
        related_name="player_attributes"
    )

class Player(models.Model):
    player_id = models.AutoField(primary_key=True)

class Attribute(models.Model):
    attribute_id = models.AutoField(primary_key=True)

我尝试使用QuerySet(?)预取它并且在打印q.query时没有在结果查询中获取我的JOIN。

这是我目前的代码:

first_attribute = PlayerAttributes.objects.filter(
    end_time=None, attribute=123
)
last_attribute = PlayerAttributes.objects.filter(
    end_time=None, attribute=456
)

players = (
    Player
    .objects
    .filter(
        player_type=789
    )
    .prefetch_related(
        Prefetch(
            "player_attributes", queryset=first_attribute,           to_attr="first_attribute"
    )
)
.prefetch_related(
    Prefetch(
        "player_attributes", queryset=last_attribute,     to_attr="last_attribute"
        )
    )
    .values("player_id", "first_attribute__value", "last_attribute__value")
)

return players

我尝试读入select_related和prefetch_related但不确定要尝试哪个? 如果重要的话我会使用Django 2.0。

如果有人可以指出我要使用的写方法或文档来查看(我很困惑在哪找/哪)这是我第一次使用Django(通常使用Flask)

提前谢谢!

0 个答案:

没有答案