我正在尝试从模型中显示单个实例(db行),其中多个实例共享多行的相同字段(列)值。为澄清该陈述,我有以下情况:
ID/Title/Slug/Modified
1 Car A 1s ago
2 Car A 2s ago
3 House B 1s ago
如果上面的小表是我的db我希望我的Django管理页面显示基于我的slug字段(列)的不同行显示最后编辑的版本(我有另一列时间...所以上面的表格会显示在管理页面中,如下所示:
ID/Title/Slug/Modified
1 Car A 1s ago
3 House B 1s ago
虽然第1行和第1行2有不同的pk,他们有相同的slug,我只希望其中一个与更晚的时间......
我可以在我的views.py中实现这一点,如下所示
existing_data = MyModel.objects.filter(slug=slug).latest('modified')
但那是因为我正在寻找一个特定的slug实例..如果我不是,我也可以使用group_by ......
我正在尝试在管理页面中显示此内容。我在模型管理器中尝试了以下技术,
class ModelManager(models.Manager):
def get_query_set(self):
return super(ModelManager, self).get_query_set().group_by('title')
但我收到此错误
'QuerySet' object has no attribute 'group_by'
然后我正在阅读this part of the Django book并且他们在模型管理器中实现了原始sql,我尝试按照以下方式复制到我的情况,
class ModelManager(models.Manager):
def uniques(self):
cursor = connection.cursor()
cursor.execute("""
SELECT *
FROM eventform_event
GROUP BY slug
""")
return [row[0] for row in cursor.fetchone()]
我是我的模特
objects = ModelManager()
我只是不确定如何让管理模型查看我的自定义管理器,它不会覆盖get_query_set。当我使用此自定义管理器覆盖get_query_set时,我收到此错误
'long' object has no attribute '__getitem__'
我也尝试过测试'values(),values_list(),distinct()等但是它们都给我错误... distinct()告诉我我的数据库(mysql)不支持这个功能..现在确定我是否必须切换数据库以实现此功能,现在我没有想法进行实验......任何人都知道如何实现此功能..谢谢。
#在我的admin.py页面中,我可以获得旁边过滤器(list_filter),以根据每this thread推荐的slug列显示唯一条目...
不幸的是,基于某个列,我无法将管理页面中显示的行显示为我的模型唯一...
答案 0 :(得分:4)
如果您在PostgreSQL中使用Django 1.4+,则可以使用带有* fields参数的queryset.distinct()。如果您使用的是较旧版本的Django或其他数据库引擎,请告诉我,我会以不同的方式进行操作。
因此,如果您的模型看起来像这样:
from django.db import models
class TestModel(models.Model):
title = models.TextField(max_length=150)
slug = models.TextField(max_length=150)
modified = models.DateTimeField(auto_now=True)
然后您可以在ModelAdmin的queryset
方法中执行此操作:
from django.contrib import admin
import models
class TestModelAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'modified')
def queryset(self, request):
qs = super(TestModelAdmin, self).queryset(request)
qs = qs.order_by('slug', '-modified').distinct('slug')
return qs
admin.site.register(models.TestModel, TestModelAdmin)
希望这有帮助。
修改强>
好吧,如果你使用的是MySQL,它就不那么整洁了。您不能使用原始SQL,因为Django管理员希望使用QuerySet而不是RawQuerySet。即使我们可以使用原始SQL,它也不会像GROUP BY slug
那么简单,因为如果你这样做,MySQL会按照它们在表中出现的顺序给出结果。因此,如果您的数据如下所示:
+----+-------+------+---------------------+
| id | title | slug | modified |
+----+-------+------+---------------------+
| 1 | Car | A | 2013-06-30 20:18:06 |
| 2 | House | B | 2013-06-30 20:18:12 |
| 3 | Car | A | 2013-06-30 21:02:51 |
| 4 | Thing | C | 2013-06-30 22:08:00 |
| 5 | House | B | 2013-06-30 22:08:05 |
+----+-------+------+---------------------+
按句子分组,无论是否有任何order by子句,都会给你id 1,2和4。我们实际上需要ID 3,4和5,否则Django管理员不会向我们显示最近修改过的条目(这就是你想要的)。因此,在我们进行任何分组之前,我们必须从预先排序的表中进行选择。
我能想到的最好的方法是将我给PostgreSQL的答案中的queryset
方法更改为:
def queryset(self, request):
qs = super(TestModelAdmin, self).queryset(request)
qs = qs.extra(where=[
"id IN (
SELECT id FROM (
SELECT * FROM myapp_testmodel ORDER BY modified DESC
) AS last_modified
GROUP BY slug)"
])
return qs
您必须将id
更改为表格主键名称,并将myapp_testmodel
更改为表格名称。