2013-06-30 57 views
4

我试图从模型中显示一个实例(db行),其中几个实例共享多行的同一个字段(列)值。为了澄清这种说法,我有以下情况:Django Admin:显示重复实例的单个实例

ID/Title/Slug/Modified 
1 Car  A 1s ago 
2 Car  A 2s ago 
3 House B 1s ago 

如果上面的小桌子是我的分贝我希望我的Django管理页面,根据我的蛞蝓字段(列)显示上一次编辑的版本(显示不同行我有时间的另一列...所以上表将在管理页面显示如下:

ID/Title/Slug/Modified 
1 Car  A 1s ago 
3 House B 1s ago 

虽然第1行& 2有不同的PK的,他们具有相同的鼻涕虫,我想只是其中之一随着时间的推移...

我可以在我的views.py如下

existing_data = MyModel.objects.filter(slug=slug).latest('modified') 

但那是因为我正在寻找一个蛞蝓的特定实例。如果我是不是我也可以使用GROUP_BY实现这个...

我试图在管理页面中显示此显示。我尝试了以下技术的模型管理器,

class ModelManager(models.Manager): 
    def get_query_set(self): 
     return super(ModelManager, self).get_query_set().group_by('title') 

,但我得到这个错误

​​

然后我读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_list(),不同的()等,但他们都给予我的错误... distinct()告诉我我的数据库(mysql)不支持这个功能..现在确定如果我必须切换数据库来实现这个功能,现在我没有想法试验...任何人都知道如何实现这个功能..谢谢。

在我的admin.py页面,我可以得到侧滤波器(list_filter)显示基于每this thread推荐slug列独特的条目...

不幸的是我不能显示在列我的模型的管理页面基于特定的列是唯一的...

回答

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 | 
+----+-------+------+---------------------+ 

通过塞分组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到您的表的名称。

+0

谢谢凯文。我使用mysql作为我的数据库引擎。我会很感激得到这个功能实施W/MySQL的任何帮助..因为我不知道这个项目是否可以移动到PostgreSQL在这一点上... – user772401

+0

感谢@Kevin,完美的工作!我不知道你可以把原始的SQL在Django的管理查询集 – user772401

+0

有没有人试过在MySQL 5.7中使用它?这不适合我。可能是由于这[问题](http://stackoverflow.com/questions/40804597/error-1055-42000-expression-1-of-select-list-is-not-in-group-by-clause-t) –