在生成 django 管理 URL 时覆盖查询集过滤器
Posted
技术标签:
【中文标题】在生成 django 管理 URL 时覆盖查询集过滤器【英文标题】:Override queryset filters while generating django admin URLs 【发布时间】:2014-07-17 23:43:43 【问题描述】:我的 models.py 看起来像这样:
class Person(models.Model):
Name = models.CharField(max_length=100)
class Lecture(models.Model):
Speaker = model.ForeignKey(Person)
Topic = models.CharField(max_length=100)
Choices = ((1,"Upcoming"),(2,"In Progress",),(3,"Completed"))
Status = models.SmallIntegerField(choices=Choices, default=1, max_length=1)
我的 admin.py 看起来像这样:
class LectureAdmin(admin.ModelAdmin):
def get_queryset(self):
return Lecture.objects.exclude(Status='Completed')
因此,我在 django 管理员中的 Lecture 模型更改列表视图仅显示处于“即将到来”和“进行中”状态的 Lectures。这很好用。
现在我需要获取所有讲座列表的 URL,以将其作为视图传递到其他地方。在 django 管理员中执行此操作的标准方法是反转 URL,所以我这样做:
urlresolvers.reverse('admin:%s_%s_changelist' % (app_label, model_name))
但是,当我这样做时,我得到了过滤后的查询集,其中 Lectures 处于“已完成”状态。如何构造一个 url 反向函数来获取整个 Lecture 查询集而不是过滤后的查询集?
【问题讨论】:
【参考方案1】:这是一个解决方法,看起来很难看,我明白。
将all
GET 参数添加到changelist
url:
url = urlresolvers.reverse('admin:%s_%s_changelist' % (app_label, model_name))
url += '?all'
在super()
上调用get_queryset()
,仅当request.GET
中没有all
时才排除Completed
状态:
class LectureAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(LectureAdmin, self).get_queryset(request)
if 'all' not in request.GET:
qs = qs.exclude(Status='Completed')
return qs
UPD(应用来自request.GET
的其他过滤器):
from xadmin.plugin.related import RELATE_PREFIX # or just set RELATE_PREFIX = '_rel_'
qs = qs.filter(**key[len(RELATE_PREFIX):]: value
for key, value in request.GET.iteritems()
if key.startswith(RELATE_PREFIX))
**
将字典解包为关键字参数。
希望它对你有用。
【讨论】:
这与我使用的查询集方法有什么不同 @Amistad 我已经更新了答案。试一试。谢谢。 这是一个聪明的 hack..为我工作..美丽在于旁观者的眼中..对我来说很漂亮!! @alecxe..我还有一个问题..我正在使用 urlresolvers 专门查找 URL,在我的情况下,这将为我提供与演讲者相关的讲座列表..我的 url have is college/lectures/?_rel_Speaker__id__exact=1 其中,college 是应用程序名称,id 是 Django 自动生成的主键。如何将您的解决方案与此设置结合起来。如果不清楚,我可以编辑我的原始问题.. 我玩了一点..这工作..qs = super(ChangeAdmin, self).queryset() if any([key for key in self.request.GET.keys() if '_rel_' in key.lower()]): qs = qs.filter(Change_status='Completed') return qs
...感谢您的帮助..【参考方案2】:
get_queryset()
是管理列表中使用的基本查询集,因此如果您以这种方式覆盖它,您将无法获取所有记录。
可能的解决方案:
使用过滤器 (https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.filter_vertical) 排除不需要的记录(这些带有Status='Completed'
或
为Lecture
创建代理模型,在管理员中注册并在给定列表中使用修改后的get_queryset()
。代理模型是必需的,因为每个模型只能注册一个 AdminModel
类
models.py
class IncompletedLecture(Lecture):
class Meta:
proxy = True
admin.py
class IncompletedAdmin(admin.ModelAdmin):
def get_queryset():
return Lecture.query.exclude(Status='Completed')
admin.site.register(IncompletedLecture, IncompletedAdmin)
【讨论】:
我在管理员中使用 django reversion 来获取对象历史记录和 reversion..Reversion 不适用于代理模型..以上是关于在生成 django 管理 URL 时覆盖查询集过滤器的主要内容,如果未能解决你的问题,请参考以下文章