newbie第一次尝试prefetch_related - 返回空白

时间:2012-05-17 02:02:18

标签: django django-models django-views

之前我问过这个问题,但我没有收到任何解决方案,所以我试图让问题简明扼要。这次更清楚。

我的数据库具有以下简化架构:

class RIAchievement(models.Model):
  riAchievementID = models.AutoField(primary_key=True, db_column="riAchievementID")
  userLanguageVersionID = models.ForeignKey(UserLanguageVersion, db_column="userLanguageVersionID", related_name="riAchievement_userLanguageVersionID")
  class Meta:
    db_table="riAchievement"

class UserLanguageVersion(models.Model):
  userLanguageVersionID = models.AutoField(primary_key=True, db_column="userLanguageVersionID")
  languageCodeID = models.ForeignKey(LanguageCode, db_column="languageCodeID", related_name="userLanguageVersion_languageCodeID")
  class Meta:
    db_table="userLanguageVersion"

class LanguageCode(models.Model):
  languagecodeID = models.AutoField(primary_key=True, db_column="languageCodeID")
  class Meta:
    db_table="languageCode"

class Flag(models.Model):
  flagID = models.AutoField(primary_key=True, db_column="flagID")
  languageCodeID = models.ForeignKey(LanguageCode, db_column="languageCodeID", related_name="flag_languageCodeID")
  flagIconPath = models.CharField(max_length=255, db_column="flagIconPath")
  class Meta:
    db_table="flag"

基本上,riachievement可以有很多用户语言版本,而userlanguageversion可以有很多语言代码,而flag可以有很多语言代码。

使用 select_related 不会返回 flag.flagIconPath 因为1对多关系,所以Django docs状态我必须使用 prefetch_related ,使用1到多个外键的相关名称

所以我在 view.py

中修改了我的代码
from django.shortcuts import render
from app_data.models import RIAchievement

def ri_achievements(request):

  qs = RIAchievement.objects.select_related("riachievement", "userlanguageversion", "languagecode", "flag_languageCodeID").all()

  return render(request, 'index.html',{'qs': qs})

我的 index.html

{% for ri_achievement in qs %}
  {{ ri_achievement.userLanguageVersionID.langaugeCodeID.flag_languageCodeID.flagIconPath }}
{% endfor %}

但是,这段代码什么也没有返回。

任何人都可以提供一些建议,因为我看不出我做错了什么?

1 个答案:

答案 0 :(得分:2)

我建议您使用django shell python manage.py shell来计算您的查询 - 通过模板“弄明白”将很难解决错误。

例如,您看起来有拼写错误,但模板不会抱怨它。

让我们将您尝试的查询分解为python,以便我们可以使用注释

flagIconPath = (ri_achievement
    .userLanguageVersionID # correct. direct FK 
    .langaugeCodeID # spelling error. but otherwise ok. direct FK
    # this is now a one to many relationship - you now have a related manager
    # NOT a single object. Many flags to one Code
    .flag_languageCodeID
    .latest('id') # you must pick which one you want - for example, the latest ID
    .flagIconPath)

至于提高此查询的效率,您的选择相关调用需要包含这些模型的完整路径。您正在传递属性,就像它们是原始模型上的所有外键一样。

qs = RIAchievement.objects.select_related('userLanguageVersionID__languageCodeID')

我不确定此时的预取调用,但它应该看起来像

qs.prefetch_related('userLanguageVersionID__languageCodeID__flag_languageCodeID')

对于所有这些嵌套调用,一个预取,它可以做出巨大的查询。你确定这是你想要的吗?