Django自定义注释功能

int*_*lis 14 python django django-queryset

我想用Django构建一个简单的热门问题列表.我有一个函数,根据一些参数评估每个问题的" 热度 ".

功能看起来与此类似(此处完整功能)

def hot(ups, downs, date):
    # Do something here..
    return hotness
Run Code Online (Sandbox Code Playgroud)

我的问题和投票模型模型(相关部分)

class Question(models.Model):
    title = models.CharField(max_length=150)
    body = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

class Vote(models.Model):
    question = models.ForeignKey(Question, related_name='questions_votes')
    delta = models.IntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)

现在,delta attribute无论是积极的还是消极的.热门功能接收正投票数和负投票数以及问题创建日期.

我尝试过类似的东西,但它没有用.

 questions = Question.objects.annotate(hotness=hot(question_votes.filter(delta, > 0),question_votes.filter(delta < 0), 'created_at')).order_by('hotness')
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:global name 'question_votes' is not defined
我理解错误,但我没有正确的方法.

Tod*_*dor 14

您不能使用python函数进行注释.注释是在数据库级别上完成的计算.Django只为您提供了一组可以由数据库处理的基本计算 - SUM,AVERAGE,MIN,MAX等等...对于仅来自1.8版本的更复杂的东西,我们有一个用于更复杂查询表达式的API .在Django 1.8之前,实现类似功能的唯一方法是使用.extra,这意味着编写纯SQL.

所以你基本上有两个半选项.

一个半月.

.extra如果您的Django版本> = 1.8,则使用或通过新API 在纯SQL中编写热度计算.

第二.

在您的模型中创建热点字段,该字段将由cron作业每天计算一次(或者更多地取决于您的需要).并根据您的需求使用它(最热门的列表).


小智 5

对于那些寻找更新答案(Django 2.0+)的人,可以根据文档对 Func 进行子类化以生成用于聚合的自定义函数。在“使用自定义数据库功能扩展”部分的帖子中,大约有 80% 的时间在这里有一个很好的解释和示例。