使用是否存在匹配的相关对象来注释查询集

时间:2016-11-14 23:38:26

标签: django django-queryset

我有两个具有明确的多对多关系的模型:一个东西,auth.user和一个连接两者的“最喜欢的”模型。我希望能够通过他们是否被特定用户收藏来命令我的“事物”。在Sqlite3中,我提出的最佳查询是(大致)这个:

select 
    *, max(u.name = "john cleese") as favorited 
    from thing as t 
        join favorite as f on f.thing_id = t.id 
        join user as u on f.user_id = u.id
    group by t.id
    order by favorited desc
    ;

在我的sql-to-django翻译中绊倒我的是max(u.name = "john cleese")位。据我所知,Django支持算术但不支持平等。我最接近的是一个case语句,它没有正确地对输出行进行分组:

Thing.objects.annotate(favorited=Case(
    When(favorites__user=john_cleese, then=Value(True)),
    default=Value(False),
    output_field=BooleanField()
))

我尝试过的另一个方向是使用RawSQL

Thing.objects.annotate(favorited=RawSQL('"auth_user"."username" = "%s"', ["john cleese"]))

但是,这不起作用,因为(据我所知),没有办法明确加入我需要的favoriteauth_user表。

我有什么遗失的吗?

3 个答案:

答案 0 :(得分:4)

这将实现您(或其他任何人在这里使用Google搜索)想要做的事情:

searchbar.setOnFocusChangeListener(new View.OnFocusChangeListener() {
        @Override
        public void onFocusChange(View view, boolean b) {
            if(b) hide();
            else Utils.closeKeyboard(MapsActivity_v2.this, view);
        }
    });

<MultiAutoCompleteTextView
                android:imeOptions="actionDone"
                android:id="@+id/searchbar"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:background="@android:color/transparent"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:hint="@string/search_hint"
                android:padding="6dp"/>

答案 1 :(得分:1)

根据我在 related ticket 中读到的内容,您可以使用带有 Exists query expression 的子查询。

<块引用>

Exists 是一个使用 SQL EXISTS 语句的子查询子类。在许多情况下,它会比子查询执行得更好,因为当找到第一个匹配的行时,数据库能够停止对子查询的评估。

假设您的 ManyToMany 中的中间模型被称为 Favorite

from django.db.models import Exists, OuterRef

is_favorited_subquery = Favorite.objects.filter(
  thing_id = OuterRef('pk')
)

Thing.objects.annotate(favorited=Exists(is_favorited_subquery))

然后您可以通过查询的 favorited 属性进行排序。

答案 2 :(得分:0)

我不确定你想要达到的目标,但我会这样开始。

from django.db import models
from django.contrib.auth.models import User

class MyUser(models.Model):             
    person = models.OneToOneField(User)

class Thing(models.Model):
    thingname = models.CharField(max_length=10)
    favorited_by = models.ManyToManyField(MyUser)

在你看来:

qs = MyUser.objects.get(id=pk_of_user_john_reese).thing_set.all()

将为您提供给定用户的所有Thing对象。

您应该查看Django Docs for ManyToMany

我在几个较小甚至更大的项目中使用Django已经有好几年了,但我从不使用了RawSQL功能。大多数时候我都在考虑它,我的模型设计中有一个错误。