Simple filter for django ModelAdmin
How use:
#models.py
class ObjectWithGenericForeignKey(model.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object= GenericForeignKey('content_type', 'object_id', for_concrete_model=False)
#admin.py
class CommentAdmin(admin.ModelAdmin):
list_filter = (get_generic_foreign_key_filter(u'Filter title'),)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | from django.contrib import admin
from django.contrib.contenttypes.models import ContentType
def get_generic_foreign_key_filter(title, parameter_name=u'', separator='-', content_type_id_field='content_type_id', object_id_field='object_id') :
class GenericForeignKeyFilter(admin.SimpleListFilter):
def __init__(self, request, params, model, model_admin):
self.separator = separator
self.title = title
self.parameter_name = u'generic_foreign_key_' + parameter_name
super(GenericForeignKeyFilter, self).__init__(request, params, model, model_admin)
def lookups(self, request, model_admin):
qs = model_admin.model.objects.all()\
.order_by(content_type_id_field, object_id_field)\
.distinct(content_type_id_field, object_id_field)\
.values_list(content_type_id_field, object_id_field)
return [
(
'{1}{0.separator}{2}'.format(self, *content_type_and_obj_id_pair),
ContentType.objects
.get(id=content_type_and_obj_id_pair[0])
.model_class()
.objects.get(pk=content_type_and_obj_id_pair[1])
.__unicode__()
)
for content_type_and_obj_id_pair
in qs
]
def queryset(self, request, queryset):
try :
content_type_id, object_id = self.value().split(self.separator)
return queryset.filter(**({
content_type_id_field:content_type_id,
object_id_field:object_id
}))
except:
return queryset
return GenericForeignKeyFilter
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
Comments
Great solution!! I'm just change
.__unicode__()
to.__str__()
andqs = model_admin.model.objects.all()\
tofilter = object_id_field + '__isnull'
qs = model_admin.model.objects.exclude(**{ filter: True })\
for use with null=True fields#
Using django 1.11 and mysql,
I had to change __unicode__() to __str__()
and qs didn't worked because of distinct (NotImplementedError: DISTINCT ON fields is not supported by this database backend), so I have changed it in this way --> qs = model_admin.model.objects.all().order_by(content_type_id_field, object_id_field) .values_list(content_type_id_field, object_id_field).distinct()
Now it works fine, thank you!
#
Nice! Works with Django 4.2 with minimal fixes (str instead of unicode).
#
Please login first before commenting.