如何将此原始查询转换为Django ORM

时间:2015-06-09 07:48:23

标签: sql django django-models django-templates

我有一个模型,我们有候选人,语言和语言水平实体:

class Candidate(models.Model):
  user = models.ForeignKey(MyUser)
  telephone = models.CharField(max_length=20, unique=True)
  postcode = models.CharField(max_length=10)

class Language(models.Model):
  name = models.CharField(max_length=50)

class LanguageLevel(models.Model):
  candidate = models.ForeignKey(Candidate)
  language = models.ForeignKey(Language)
  level = models.IntegerField(max_length=1, choices=LANGUAGE_LEVEL, default=0)

我的原始查询是:

SELECT c.id, COUNT(c.id) as total
FROM candidates as c
  JOIN language_level as ll ON ll.candidate_id=c.id
  JOIN languages as l ON ll.language_id=l.id
WHERE ((ll.level >=1 AND l.id = 1 ) OR
       (ll.level >=1 AND l.id = 2 ) OR
       (ll.level >=1 AND l.id = 3 ) OR
       (ll.level >=3 AND l.id = 4 ) OR
       (ll.level >=3 AND l.id = 5 ) OR
       (ll.level >=2 AND l.id = 6 ))
GROUP By c.id

我需要能够通过总字段对结果进行排序,并且还需要能够在模板中显示该总计。不知何故,我需要创建一个更大的对象列表,将这3个实体+组合在一起。

知道什么是最好的方法吗?我尝试获取候选人的ID并只做一个Candidates.objects.find(id__in = ids),但以后没办法对此进行排序。

提前致谢

2 个答案:

答案 0 :(得分:1)

Candidate.objects.filter(
    Q(Q(languagelevel__language__id__in=(1, 2, 3)) & Q(languagelevel__language__level__gte=1)) |
    Q(Q(languagelevel__language__id__in=(4, 5)) & Q(languagelevel__language__level__gte=3)) |
    Q(Q(languagelevel__language__id=6) & Q(languagelevel__language__level__gte=2))
)).values('id').annotate(total=Count('id'))

values只会返回每位候选人的id,其总计为total

如果您想获取所有字段(不仅是ID),可以将.values('id')删除为:

Candidate.objects.filter(
    Q(Q(languagelevel__language__id__in=(1, 2, 3)) & Q(languagelevel__language__level__gte=1)) |
    Q(Q(languagelevel__language__id__in=(4, 5)) & Q(languagelevel__language__level__gte=3)) |
    Q(Q(languagelevel__language__id=6) & Q(languagelevel__language__level__gte=2))
)).annotate(total=Count('id'))

答案 1 :(得分:0)

我真的没有看到你的SQL如何完成你在评论中描述的内容。但是,此代码与该描述类似。

from django.db.models import Max
Candidate.objects.filter(
    languagelevel__language__name__in=['English', 'Spanish'],
    languagelevel__level__gte=2
).annotate(max_level=Max('languagelevel__level')).order_by('max_level')