我的models.py:
来自django.db导入模型 来自django.contrib.auth.models导入用户
class SkillCategory(models.Model):
title = models.CharField(max_length=255)
def __unicode__(self):
return self.title
class Meta:
verbose_name_plural = "Skill Categories"
class Skill(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey(
SkillCategory, default=None, null=True, blank=True
)
def __unicode__(self):
return self.title
class UserProfile(models.Model):
user = models.OneToOneField(User)
skill = models.ManyToManyField(Skill)
avatar = models.URLField(
max_length=400, default=None, null=True, blank=True
)
def __unicode__(self):
return self.user.username
我的views.py:
def ShowUserProfile(request, username=None, template_name='user_profile.html'):
if not username:
username = request.user.username
profile = get_object_or_404(
UserProfile.objects.select_related(), user__username=username
)
...
在我的模板中,我这样迭代:
...
{% if skill.category.title == 'Some Skill' %}
{% for skill in profile.skill.all %}
<li>{{ skill }}</li>
{% endfor %}
{% endif %}
...
但是如果我查看Django Debug Toolbar,我会看到每个Skill
,Django正在查询数据库以获取Category
。我在select_related
对象上使用UserProfile
但它不会影响查询的数量。肯定有一个更好的方法,Django可以一次性获得所有Skill
和相关的SkillCategory
引用?
非常感谢任何帮助。
修改
根据准确的反馈,正确的视图如下所示:
def ShowUserProfile(request, username=None, template_name='user_profile.html'):
if not username:
username = request.user.username
profile = get_object_or_404(
UserProfile.objects.prefetch_related(
'skill__category'), user__username=username
)
答案 0 :(得分:2)
select_related
无法处理ManyToMany关系。查看prefetch_related
,它通过运行两个查询并在Python中连接结果来处理ManyToMany字段。
select_related通过创建SQL连接并在SELECT语句中包含相关对象的字段来工作。因此,select_related在同一数据库查询中获取相关对象。但是,为了避免加入“多”关系会产生更大的结果集,select_related仅限于单值关系 - 外键和一对一。
另一方面,prefetch_related对每个关系进行单独查找,并在Python中进行“加入”。这允许它预取多对多和多对一对象,除了select_related支持的外键和一对一关系之外,这些对象无法使用select_related完成。它还支持预取GenericRelation和GenericForeignKey。
答案 1 :(得分:1)
Django的select_related
不适用于many-to-many
关系。
查看prefetch_related