use*_*401 5 django django-models django-admin
我试图从模型中显示单个实例(db行),其中多个实例共享多行的相同字段(列)值.为澄清该陈述,我有以下情况:
ID/Title/Slug/Modified
1 Car A 1s ago
2 Car A 2s ago
3 House B 1s ago
Run Code Online (Sandbox Code Playgroud)
如果上面的小表是我的db我希望我的Django管理页面显示基于我的slug字段(列)的不同行显示最后编辑的版本(我有另一列时间...所以上面的表将显示在管理页面如下:
ID/Title/Slug/Modified
1 Car A 1s ago
3 House B 1s ago
Run Code Online (Sandbox Code Playgroud)
虽然第1行和第2行有不同的pk,但它们具有相同的slug,我只希望其中一个具有较晚的时间......
我可以在我的views.py中实现这一点,如下所示
existing_data = MyModel.objects.filter(slug=slug).latest('modified')
Run Code Online (Sandbox Code Playgroud)
但那是因为我正在寻找一个slu_的特定实例..如果我不是,我也可以使用group_by ...
我正试图在管理页面中显示此内容.我在模型管理器中尝试了以下技术,
class ModelManager(models.Manager):
def get_query_set(self):
return super(ModelManager, self).get_query_set().group_by('title')
Run Code Online (Sandbox Code Playgroud)
但是我得到了这个错误
'QuerySet' object has no attribute 'group_by'
Run Code Online (Sandbox Code Playgroud)
然后我正在阅读这部分Django书,他们在模型管理器中实现了原始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()]
Run Code Online (Sandbox Code Playgroud)
我是我的模特
objects = ModelManager()
Run Code Online (Sandbox Code Playgroud)
我只是不确定如何让管理模型查看我的自定义管理器,它不会覆盖get_query_set.当我使用此自定义管理器覆盖get_query_set时,我收到此错误
'long' object has no attribute '__getitem__'
Run Code Online (Sandbox Code Playgroud)
我也试过测试'values(),values_list(),distinct()等但是它们都给我错误... distinct()告诉我我的数据库(mysql)不支持这个功能..现在确定如果我必须切换数据库来实现这个功能,现在我没有想要试验...任何人都知道如何实现这个功能..谢谢.
#在我的admin.py页面中,我可以获得侧过滤器(list_filter),以根据每个线程建议的slug列显示唯一条目...
遗憾的是,根据某个列,我无法将管理页面中显示的行显示为我的模型的唯一性...
如果您将 Django 1.4+ 与 PostgreSQL 一起使用,您可以使用带有 *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)
Run Code Online (Sandbox Code Playgroud)
然后您可以在 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)
Run Code Online (Sandbox Code Playgroud)
希望这有帮助。
编辑:
好的,如果你使用 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 |
+----+-------+------+---------------------+
Run Code Online (Sandbox Code Playgroud)
无论任何 order by 子句如何,按 slug 分组都会为您提供 ids 1,2 和 4。我们实际上想要 ids 3、4 和 5,否则 Django 管理员将不会向我们显示最近修改的条目(这就是您所说的)。因此,在我们进行任何分组之前,我们必须从预先排序的表格中进行选择。
我能想到的最好方法是将queryset
我为 PostgreSQL 给出的答案中的方法更改为:
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
Run Code Online (Sandbox Code Playgroud)
您必须更改id
为表的主键myapp_testmodel
名称和表的名称。
归档时间: |
|
查看次数: |
2203 次 |
最近记录: |