我有模特:
class Article(models.Model):
site = models.ForeignKey('Site')
published_at = models.DateTimeField(_('Published at'))
promoted = models.BooleanField(_('Promoted'))
position = models.PositiveSmallIntegerField(
_('Position'),
null=True,
blank=True,
)
valid_from = models.DateTimeField(_('Valid from'))
valid_to = models.DateTimeField(_('Valid to'))
// (...)
我希望查询集在指定的时间范围内具有某些对象的指定位置。其余部分应按published
日期订购。
我这样做的方式现在有效,但速度慢且效率不高,这是一个问题,因为我想在主页上使用它。
def get_articles_list(site):
articles = Article.objects.filter(
site=site,
published_at__lte=now(),
).order_by(
'-published_at',
)
promoted_articles = Article.objects.filter(
site=site,
promoted=True,
valid_from__lte=now(),
valid_to__gte=now(),
position__isull=False,
)
// create a list with no promoted articles on it (to avoid duplicates)
articles_list = list(articles.exclude(id__in=promoted_articles))
// put promoted articles on the specific positions of the list
if promoted_articles:
for promoted in promoted_articles:
articles_list.insert(promoted.position - 1, promoted)
return articles_list
有没有办法优化流程?
更新
例如,我有五个Article
个对象:
article_1
site: 1
published_at: 2018-04-01
promoted: True
position: 4
valid_from: 2018-04-01
valid_to: <tomorrow>
article_2
site: 1
published_at: 2018-04-02
promoted: False
position: -
valid_from: -
valid_to: -
article_3
site: 1
published_at: 2018-04-03
promoted: False
position: -
valid_from: -
valid_to: -
article_4
site: 1
published_at: 2018-04-04
promoted: False
position: -
valid_from: -
valid_to: -
article_5
site: 1
published_at: 2018-04-05
promoted: True
position: 2
valid_from: 2018-04-05
valid_to: <tomorrow>
我想要达到的顺序是:
[article_4, article_5, article_3, article_1, article_2]
答案 0 :(得分:1)
我建议你添加一些中间件方法,根据一些自定义逻辑计算每个条目的权重 - 你需要定义什么参数将使列表前面的条目更加提升,哪些是中性的。
我认为这就是(或多或少)像Algolia这样的搜索服务(或者只是他们功能的一部分)的工作方式,在这里你可以定义什么样的分数&#39;乘数有你数据库中的一些参数。
(抱歉没有实际的Python代码,但我不是每天都使用它 - 只是想帮助解决一般的解决方案概念)
答案 1 :(得分:0)
尝试这样的事情:
from django.db.models import Q
filters = Q(published_at_lte=now(), promoted=False)
filters.add(
Q(promoted=True,
valid_from__lte=now(),
valid_to__gte=now(),
position__isnull=False),
Q.OR
)
articles = (
Article.objects
.filter(site=site)
.filter(filters)
.order_by(
'-promoted',
'position',
'-published_at'
)
)
答案 2 :(得分:0)
首先获取promoted
,然后按降序排列published_at
。
Article.objects.filter(site=site).order_by('promoted', 'position', '-published_at')
https://docs.djangoproject.com/en/2.0/ref/models/querysets/#order-by