Merge pull request #332 from nephila/feature/improve_admin
Improve admin filtering
This commit is contained in:
commit
68dede34b2
6 changed files with 96 additions and 4 deletions
|
@ -19,6 +19,7 @@ History
|
||||||
* Added plugins templateset.
|
* Added plugins templateset.
|
||||||
* Improved category admin to avoid circular relationships.
|
* Improved category admin to avoid circular relationships.
|
||||||
* Dropped strict dependency on aldryn-search, haystack. Install separately for search support.
|
* Dropped strict dependency on aldryn-search, haystack. Install separately for search support.
|
||||||
|
* Improved admin filtering.
|
||||||
|
|
||||||
******************
|
******************
|
||||||
0.8.9 (unreleased)
|
0.8.9 (unreleased)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from copy import deepcopy
|
||||||
|
|
||||||
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
|
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
|
||||||
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
|
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
|
||||||
from cms.models import CMSPlugin
|
from cms.models import CMSPlugin, ValidationError
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -14,7 +14,7 @@ from django.contrib import admin
|
||||||
from django.contrib.sites.models import Site
|
from django.contrib.sites.models import Site
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.utils.six import callable
|
from django.utils.six import callable, text_type
|
||||||
from django.utils.translation import get_language_from_request, ugettext_lazy as _
|
from django.utils.translation import get_language_from_request, ugettext_lazy as _
|
||||||
from parler.admin import TranslatableAdmin
|
from parler.admin import TranslatableAdmin
|
||||||
|
|
||||||
|
@ -30,6 +30,30 @@ except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SiteListFilter(admin.SimpleListFilter):
|
||||||
|
title = _('site')
|
||||||
|
parameter_name = 'sites'
|
||||||
|
|
||||||
|
def lookups(self, request, model_admin):
|
||||||
|
restricted_sites = model_admin.get_restricted_sites(request).values_list('id', flat=True)
|
||||||
|
|
||||||
|
qs = Site.objects.all()
|
||||||
|
if restricted_sites:
|
||||||
|
qs = qs.filter(id__in=restricted_sites)
|
||||||
|
|
||||||
|
return [(site.id, text_type(site.name)) for site in qs]
|
||||||
|
|
||||||
|
def queryset(self, request, queryset):
|
||||||
|
try:
|
||||||
|
if 'sites' in self.used_parameters:
|
||||||
|
return queryset.on_site(Site.objects.get(pk=self.used_parameters['sites']))
|
||||||
|
return queryset
|
||||||
|
except Site.DoesNotExist as e: # pragma: no cover
|
||||||
|
raise admin.options.IncorrectLookupParameters(e)
|
||||||
|
except ValidationError as e: # pragma: no cover
|
||||||
|
raise admin.options.IncorrectLookupParameters(e)
|
||||||
|
|
||||||
|
|
||||||
class BlogCategoryAdmin(EnhancedModelAdminMixin, ModelAppHookConfig, TranslatableAdmin):
|
class BlogCategoryAdmin(EnhancedModelAdminMixin, ModelAppHookConfig, TranslatableAdmin):
|
||||||
form = CategoryAdminForm
|
form = CategoryAdminForm
|
||||||
list_display = [
|
list_display = [
|
||||||
|
@ -55,7 +79,7 @@ class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
|
||||||
'title', 'author', 'date_published', 'app_config', 'all_languages_column',
|
'title', 'author', 'date_published', 'app_config', 'all_languages_column',
|
||||||
'date_published_end'
|
'date_published_end'
|
||||||
]
|
]
|
||||||
list_filter = ('app_config',)
|
search_fields = ('translations__title',)
|
||||||
date_hierarchy = 'date_published'
|
date_hierarchy = 'date_published'
|
||||||
raw_id_fields = ['author']
|
raw_id_fields = ['author']
|
||||||
frontend_editable_fields = ('title', 'abstract', 'post_text')
|
frontend_editable_fields = ('title', 'abstract', 'post_text')
|
||||||
|
@ -85,6 +109,21 @@ class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
|
||||||
}
|
}
|
||||||
_sites = None
|
_sites = None
|
||||||
|
|
||||||
|
def get_list_filter(self, request):
|
||||||
|
filters = ['app_config', 'publish', 'date_published']
|
||||||
|
if get_setting('MULTISITE'):
|
||||||
|
filters.append(SiteListFilter)
|
||||||
|
try:
|
||||||
|
from taggit_helpers.admin import TaggitListFilter
|
||||||
|
filters.append(TaggitListFilter)
|
||||||
|
except ImportError: # pragma: no cover
|
||||||
|
try:
|
||||||
|
from taggit_helpers import TaggitListFilter
|
||||||
|
filters.append(TaggitListFilter)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
return filters
|
||||||
|
|
||||||
def get_urls(self):
|
def get_urls(self):
|
||||||
"""
|
"""
|
||||||
Customize the modeladmin urls
|
Customize the modeladmin urls
|
||||||
|
|
|
@ -39,6 +39,10 @@ If you want to enable haystack support, in addition to the above:
|
||||||
* configure haystack according to `aldryn-search docs <https://github.com/aldryn/aldryn-search#usage>`_
|
* configure haystack according to `aldryn-search docs <https://github.com/aldryn/aldryn-search#usage>`_
|
||||||
and `haystack docs <http://django-haystack.readthedocs.io/en/stable/>`_.
|
and `haystack docs <http://django-haystack.readthedocs.io/en/stable/>`_.
|
||||||
|
|
||||||
|
To enable taggit filtering support in the admin install djangocms-blog with::
|
||||||
|
|
||||||
|
pip install djangocms-blog[taggit]
|
||||||
|
|
||||||
*********************
|
*********************
|
||||||
Minimal configuration
|
Minimal configuration
|
||||||
*********************
|
*********************
|
||||||
|
|
|
@ -11,3 +11,4 @@ wheel
|
||||||
pysolr
|
pysolr
|
||||||
django-parler>=1.6
|
django-parler>=1.6
|
||||||
aldryn-search
|
aldryn-search
|
||||||
|
django-taggit-helpers
|
||||||
|
|
3
setup.py
3
setup.py
|
@ -42,7 +42,8 @@ setup(
|
||||||
'djangocms-apphook-setup',
|
'djangocms-apphook-setup',
|
||||||
],
|
],
|
||||||
extras_require={
|
extras_require={
|
||||||
'search': ['aldryn-search']
|
'search': ['aldryn-search'],
|
||||||
|
'taggit-helpers': ['django-taggit-helpers']
|
||||||
},
|
},
|
||||||
license='BSD',
|
license='BSD',
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
|
|
|
@ -90,6 +90,52 @@ class AdminTest(BaseTest):
|
||||||
self.assertEqual(response.status_code, 302)
|
self.assertEqual(response.status_code, 302)
|
||||||
self.assertEqual(response['Location'], '/')
|
self.assertEqual(response['Location'], '/')
|
||||||
|
|
||||||
|
def test_admin_changelist_view(self):
|
||||||
|
posts = self.get_posts()
|
||||||
|
post_admin = admin.site._registry[Post]
|
||||||
|
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
|
||||||
|
|
||||||
|
# Normal changelist, all existing posts
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
self.assertEqual(response.context_data['cl'].queryset.count(), len(posts))
|
||||||
|
self.assertTrue(posts[0] in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
|
# Site 2 is added to first post, but no changelist filter, no changes
|
||||||
|
posts[0].sites.add(self.site_2)
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
self.assertTrue(posts[0] in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
|
# Filtering on site, first post not shown
|
||||||
|
request = self.get_page_request('/', self.user, r'/en/blog/?sites=1', edit=False)
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
self.assertEqual(response.context_data['cl'].queryset.count(), len(posts) - 1)
|
||||||
|
self.assertTrue(posts[0] not in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
|
# Removing site filtering, first post appears again
|
||||||
|
request = self.get_page_request('/', self.user, r'/en/blog/?', edit=False)
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
self.assertEqual(response.context_data['cl'].queryset.count(), len(posts))
|
||||||
|
self.assertTrue(posts[0] in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
|
# Filtering on the apphook config and site
|
||||||
|
request = self.get_page_request('/', self.user, r'/en/blog/?app_config__id__exact=1&sites=1', edit=False)
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
# First and last post in the list are now in the queryset
|
||||||
|
self.assertEqual(response.context_data['cl'].queryset.count(), len(posts) - 2)
|
||||||
|
self.assertTrue(posts[0] not in response.context_data['cl'].queryset.all())
|
||||||
|
self.assertTrue(posts[-1] not in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
|
# Publishing one post, two published in total
|
||||||
|
posts[1].publish = True
|
||||||
|
posts[1].save()
|
||||||
|
published = Post.objects.published(current_site=False)
|
||||||
|
request = self.get_page_request('/', self.user, r'/en/blog/?publish__exact=1', edit=False)
|
||||||
|
response = post_admin.changelist_view(request)
|
||||||
|
# The admin queryset and the model queryset are the same
|
||||||
|
self.assertEqual(response.context_data['cl'].queryset.count(), published.count())
|
||||||
|
# Published post is in the changelist queryset
|
||||||
|
self.assertTrue(posts[1] in response.context_data['cl'].queryset.all())
|
||||||
|
|
||||||
def test_admin_blogconfig_views(self):
|
def test_admin_blogconfig_views(self):
|
||||||
post_admin = admin.site._registry[BlogConfig]
|
post_admin = admin.site._registry[BlogConfig]
|
||||||
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
|
request = self.get_page_request('/', self.user, r'/en/blog/', edit=False)
|
||||||
|
|
Loading…
Reference in a new issue