这是我的Django课程:
class MyClass(models.Model):
my_integer = models.IntegerField()
created_ts = models.DateTimeField(default=datetime.utcnow, editable=False)
我想检索MyClass
的每个唯一值为created_ts
的最新my_integer
的实例。我无法弄明白该怎么做。
有人可以告诉我该怎么做吗?
答案 0 :(得分:4)
这会帮助您
['Rafael-Debit', 'Daniel-Credit', 'Monica-Debit', 'Monica-Credit']
表格中的数据
from django.db.models import Count, Max
MyClass.objects.values('my_integer').annotate(count=Count("my_integer"),latest_date=Max('created_ts'))
<强>输出强>
my_integer created_ts
- -----------
1 2015-09-08 20:05:51.144321+00:00
1 2015-09-08 20:08:40.687936+00:00
3 2015-09-08 20:08:58.472077+00:00
2 2015-09-08 20:09:08.493748+00:00
2 2015-09-08 20:10:20.906069+00:00
答案 1 :(得分:0)
未测试
results = MyClass.objects.all().distinct('my_integer').order_by('created_ts')
答案 2 :(得分:0)
MyClass.objects.order_by('my_integer', '-created_ts').distinct('my_integer')
根据distinct,您需要按照order_by
中的顺序调用不同的属性。因此,基于整数然后在反向时间戳中对元素进行排序,并在它们上调用distinct,它返回每个整数的最新实例。
答案 3 :(得分:0)
试试这个;
// create the sharepoint chrome control
var nav = new SP.UI.Controls.Navigation("chrome_ctrl_container", spChromeControlData);
// show chrome control
nav.setVisible(true);
// hide top app chrome (image & app name)
nav.setBottomHeaderVisible(false);
//fix issues with chrome ctrl
$('body').on('click', '.ms-core-menu-root', function () {
$(this).attr("href", "javascript:;")
});
logger.log("spAppChrome loaded", null, controllerId);
common.activateController([], controllerId);
}
答案 4 :(得分:0)
这是一个非常基本的方法。假设您拥有的数据量不是很大,那么这将非常有效。您可以通过覆盖get_queryset
函数并返回过滤来在视图中使用它。或者,如果您计划在任何地方使用它,您可以将它用作课程中的静态方法。
values = MyClass.objects.order_by('-created_ts').all()
filtered = []
existing = []
for value in values:
if value.my_integer not in existing:
existing.append(value.my_integer)
filtered.append(value)
由于列表是按最近的顺序排序的,因此它们将被添加到该整数的现有列表中。我用它进行了一些基本的测试,但并不多,所以可能存在一两个缺陷。 使用sqlite进行测试。
修改强>
这是一个更快的版本。
def iter_tools():
import itertools
qs = MyClass.objects.all()
filtered = []
group_by = itertools.groupby(qs, lambda x: x.my_integer)
for x in group_by:
filtered.append(sorted(x[1], key=lambda x: x.created_ts, reverse=True)[0])
return filtered
本质上,它的工作方式是从数据库中获取所有对象,按整数对它们进行分组,然后根据时间戳对每个组进行排序,并从每个组中获取第一个。超越这个超出我的技能,但我相信有一些方法。
这是前一个timeit
与之前的In[]: timeit.timeit(manual, number=1500)
Out[]: 0.5577559471130371
In[]: timeit.timeit(iter_tools, number=1500)
Out[]: 0.39012885093688965
-----------------------------------------------
In[]: timeit.timeit(manual, number=5000)
Out[]: 1.770777940750122
In[]: timeit.timeit(iter_tools, number=5000)
Out[]: 1.2411231994628906
只有6个条目:
datetime.now()
编辑2:
我为数据库创建了60000个对象,以便用一些数据进行试验。我使用django-fixtureless生成数据,因此整数是完全随机的,并且所有这些数据的时间戳都是每个对象的新In[]: timeit.timeit(manual, number=1)
Out[]: 11.946185827255249
In[]: timeit.timeit(iter_tools, number=1)
Out[]: 0.7811920642852783
In[]: timeit.timeit(iter_tools, number=100)
Out[]: 77.93837308883667
In[]: MyClass.objects.all().count()
Out[]: 60000
。
In[16]: MyClass.objects.all().count()
Out[16]: 60000
In[17]: timeit.timeit(iter_tools, number=100)
Out[17]: 49.636733055114746
In[18]: timeit.timeit(iter_tools, number=1)
Out[18]: 0.4923059940338135
关于数据库的说明:在上面的示例中,我在本地计算机上使用了sqlite3。我刚刚设置了一个快速的小型mysql服务器作为vm并获得了更好的速度结果。
h1 {
}
h1{
color: bisque;
}
h2{
color: bisque;
}
body {
background-color: aquamarine;
}
无论哪种方式,都会返回相同的对象。如果性能是一个问题,我建议使用itertools one或自定义sql查询。
答案 5 :(得分:0)
您可以执行原始查询:
MyClass.objects.raw("""
SELECT m1.id, m1.my_integer, m1.created_ts
FROM app_myclass AS m1, (
SELECT my_integer, MAX(created_ts) AS max_created_ts
FROM app_myclass
GROUP BY my_integer
) AS m2
WHERE m1.my_integer = m2.my_integer AND m1.created_ts = m2.max_created_ts
"""))
或者使用Django ORM:
MyClass.objects.filter(
created_ts__in=MyClass.objects.values(
"my_integer"
).annotate(
created_ts=models.Max(
"created_ts"
)
).values_list("created_ts", flat=True)
)
请注意,这只需要一个SQL请求,您可以通过在查询之前和之后打印len(django.db.connection.queries)
来查看。
但是,请注意,后一种解决方案仅在保证created_ts
属性唯一时才有效,这可能不是您的情况。
如果您不愿意在created_ts
上使用原始查询或索引,那么您应该开始使用PostgreSQL及其DISTINCT ON
功能,如其他答案所示。