Django 查询仅过滤具有特定字段名称的第一个对象

Django query to filter only first objects with particular field names

型号

class UserAction(models.Model):
    ACTION_CHOICES = (
        ("LogIn", "Entered"),
        ("LogOut", "Gone Out"),
        ("Away", "Away from Computer"),
        ("Busy", "Busy"),
        ("DoNotDisturb", "Do not disturb"),
        ("Online", "Online and Available"),
    )
    action_name = models.CharField(choices=ACTION_CHOICES, default="LogIn")
    user = models.ForeignKey(Profile, related_name="actions")
    action_time = models.DateTimeField(default=timezone.now(), editable=False)


class Profile(models.Model):
    name = models.CharField(max_length=120)
    is_active = models.BooleanField(default=True)
    date_joined = models.DateTimeField(default=timezone.now())

我需要查询 UserAction,这样我只需要每个用户的最后一个 UserAction。我的解决方案太耗时了。这就是寻找优化答案的原因。

您可以使用 Subquery expression [Django-doc]:

注释 Profile
from django.db.models import OuterRef, Subquery

Profile.objects.annotate(
    last_action=<strong>Subquery(</strong>
        UserAction.objects.filter(
            user_id=OuterRef('pk')
        ).order_by('-action_time').values('action_name')[:1]
    <strong>)</strong>
)

查询集中的 Profile 将有一个额外的属性 .last_action 与最后一个相关的 UserAction.

action_name

Note: Django's DateTimeField [Django-doc] has a auto_now_add=… parameter [Django-doc] to work with timestamps. This will automatically assign the current datetime when creating the object, and mark it as non-editable (editable=False), such that it does not appear in ModelForms by default.