djangocms_blog/djangocms_blog/admin.py

374 lines
14 KiB
Python
Raw Normal View History

2014-01-04 16:07:09 +00:00
# -*- coding: utf-8 -*-
2015-09-12 22:46:05 +00:00
from __future__ import absolute_import, print_function, unicode_literals
2015-07-04 10:48:59 +00:00
from copy import deepcopy
2015-09-19 23:11:14 +00:00
from aldryn_apphooks_config.admin import BaseAppHookConfig, ModelAppHookConfig
2015-07-18 15:33:36 +00:00
from cms.admin.placeholderadmin import FrontendEditableAdminMixin, PlaceholderAdminMixin
from cms.models import CMSPlugin, ValidationError
2015-07-04 10:48:59 +00:00
from django import forms
2016-06-05 21:11:58 +00:00
from django.apps import apps
from django.conf import settings
2016-02-11 18:25:05 +00:00
from django.conf.urls import url
2015-07-04 10:48:59 +00:00
from django.contrib import admin
2016-05-22 10:08:39 +00:00
from django.contrib.sites.models import Site
2016-02-11 22:02:20 +00:00
from django.core.urlresolvers import reverse
2016-02-11 18:25:05 +00:00
from django.http import HttpResponseRedirect
from django.utils.six import callable, text_type
2016-02-11 22:02:20 +00:00
from django.utils.translation import get_language_from_request, ugettext_lazy as _
from parler.admin import TranslatableAdmin
2014-01-04 16:07:09 +00:00
2015-09-19 23:11:14 +00:00
from .cms_appconfig import BlogConfig
from .forms import CategoryAdminForm, PostAdminForm
2015-07-18 15:33:36 +00:00
from .models import BlogCategory, Post
2014-10-11 10:23:36 +00:00
from .settings import get_setting
2014-01-04 16:07:09 +00:00
2015-07-19 08:36:52 +00:00
try:
from admin_enhancer.admin import EnhancedModelAdminMixin
except ImportError:
class EnhancedModelAdminMixin(object):
pass
2014-01-04 16:07:09 +00:00
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:
2016-09-19 13:39:06 +00:00
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)
2015-09-19 23:11:14 +00:00
class BlogCategoryAdmin(EnhancedModelAdminMixin, ModelAppHookConfig, TranslatableAdmin):
form = CategoryAdminForm
list_display = [
2016-08-03 07:18:55 +00:00
'name', 'parent', 'app_config', 'all_languages_column',
]
2014-01-09 08:54:40 +00:00
def get_prepopulated_fields(self, request, obj=None):
2015-09-19 23:11:14 +00:00
app_config_default = self._app_config_select(request, obj)
if app_config_default is None and request.method == 'GET':
return {}
return {'slug': ('name',)}
2014-01-04 16:07:09 +00:00
class Media:
css = {
2015-09-19 23:11:14 +00:00
'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),)
}
2014-01-04 16:07:09 +00:00
2015-09-19 23:11:14 +00:00
class PostAdmin(PlaceholderAdminMixin, FrontendEditableAdminMixin,
ModelAppHookConfig, TranslatableAdmin):
form = PostAdminForm
2015-09-30 07:09:28 +00:00
list_display = [
'title', 'author', 'date_published', 'app_config', 'all_languages_column',
'date_published_end'
2015-09-30 07:09:28 +00:00
]
search_fields = ('translations__title',)
2014-01-04 16:07:09 +00:00
date_hierarchy = 'date_published'
raw_id_fields = ['author']
frontend_editable_fields = ('title', 'abstract', 'post_text')
2014-01-04 16:07:09 +00:00
enhance_exclude = ('main_image', 'tags')
_fieldsets = [
2014-01-04 16:07:09 +00:00
(None, {
2016-06-23 07:57:08 +00:00
'fields': [['title', 'categories', 'publish', 'app_config']]
2014-01-04 16:07:09 +00:00
}),
('Info', {
2016-06-23 07:57:08 +00:00
'fields': [['slug', 'tags'],
['date_published', 'date_published_end'],
['enable_comments']],
'classes': ('collapse',)
}),
('Images', {
2016-06-23 07:57:08 +00:00
'fields': [['main_image', 'main_image_thumbnail', 'main_image_full']],
'classes': ('collapse',)
}),
('SEO', {
2016-06-23 07:57:08 +00:00
'fields': [['meta_description', 'meta_title', 'meta_keywords']],
'classes': ('collapse',)
2014-01-04 16:07:09 +00:00
}),
]
2015-09-19 23:11:14 +00:00
app_config_values = {
'default_published': 'publish'
}
_sites = None
2015-09-19 23:11:14 +00:00
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)
2016-09-19 13:39:06 +00:00
except ImportError: # pragma: no cover
try:
from taggit_helpers import TaggitListFilter
filters.append(TaggitListFilter)
except ImportError:
pass
return filters
2016-02-11 18:25:05 +00:00
def get_urls(self):
2016-02-12 07:02:23 +00:00
"""
Customize the modeladmin urls
"""
2016-02-11 18:25:05 +00:00
urls = [
url(r'^publish/([0-9]+)/$', self.admin_site.admin_view(self.publish_post),
name='djangocms_blog_publish_article'),
]
urls.extend(super(PostAdmin, self).get_urls())
return urls
2016-07-12 20:11:50 +00:00
def post_add_plugin(self, request, obj1, obj2=None):
if isinstance(obj1, CMSPlugin):
plugin = obj1
elif isinstance(obj2, CMSPlugin):
plugin = obj2
2016-04-10 17:47:36 +00:00
if plugin.plugin_type in get_setting('LIVEBLOG_PLUGINS'):
plugin = plugin.move(plugin.get_siblings().first(), 'first-sibling')
2016-07-12 20:11:50 +00:00
if isinstance(obj1, CMSPlugin):
return super(PostAdmin, self).post_add_plugin(request, plugin)
elif isinstance(obj2, CMSPlugin):
return super(PostAdmin, self).post_add_plugin(request, obj1, plugin)
2016-04-10 17:47:36 +00:00
2016-02-11 18:25:05 +00:00
def publish_post(self, request, pk):
2016-02-12 07:02:23 +00:00
"""
Admin view to publish a single post
2016-02-12 07:02:23 +00:00
:param request: request
:param pk: primary key of the post to publish
:return: Redirect to the post itself (if found) or fallback urls
"""
2016-02-11 18:25:05 +00:00
language = get_language_from_request(request, check_path=True)
try:
post = Post.objects.get(pk=int(pk))
post.publish = True
post.save()
return HttpResponseRedirect(post.get_absolute_url(language))
except Exception:
try:
return HttpResponseRedirect(request.META['HTTP_REFERER'])
except KeyError:
return HttpResponseRedirect(reverse('djangocms_blog:posts-latest'))
2015-07-04 10:48:59 +00:00
def formfield_for_dbfield(self, db_field, **kwargs):
field = super(PostAdmin, self).formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'meta_description':
original_attrs = field.widget.attrs
original_attrs['maxlength'] = 160
field.widget = forms.TextInput(original_attrs)
elif db_field.name == 'meta_title':
field.max_length = 70
return field
def has_restricted_sites(self, request):
"""
Whether the current user has permission on one site only
:param request: current request
:return: boolean: user has permission on only one site
"""
sites = self.get_restricted_sites(request)
return sites and sites.count() == 1
def get_restricted_sites(self, request):
"""
The sites on which the user has permission on.
To return the permissions, the method check for the ``get_sites``
method on the user instance (e.g.: ``return request.user.get_sites()``)
which must return the queryset of enabled sites.
If the attribute does not exists, the user is considered enabled
for all the websites.
:param request: current request
:return: boolean or a queryset of available sites
"""
2016-08-25 13:31:15 +00:00
try:
return request.user.get_sites()
except AttributeError: # pragma: no cover
return Site.objects.none()
def _set_config_defaults(self, request, form, obj=None):
form = super(PostAdmin, self)._set_config_defaults(request, form, obj)
sites = self.get_restricted_sites(request)
if 'sites' in form.base_fields and sites.exists():
form.base_fields['sites'].queryset = self.get_restricted_sites(request).all()
return form
def get_fieldsets(self, request, obj=None):
2016-02-12 07:02:23 +00:00
"""
Customize the fieldsets according to the app settings
2016-02-12 07:02:23 +00:00
:param request: request
:param obj: post
:return: fieldsets configuration
"""
2015-09-19 23:11:14 +00:00
app_config_default = self._app_config_select(request, obj)
if app_config_default is None and request.method == 'GET':
return super(PostAdmin, self).get_fieldsets(request, obj)
if not obj:
config = app_config_default
else:
config = obj.app_config
fsets = deepcopy(self._fieldsets)
2015-09-19 23:11:14 +00:00
if config:
if config.use_abstract:
fsets[0][1]['fields'].append('abstract')
if not config.use_placeholder:
fsets[0][1]['fields'].append('post_text')
else:
if get_setting('USE_ABSTRACT'):
fsets[0][1]['fields'].append('abstract')
if not get_setting('USE_PLACEHOLDER'):
fsets[0][1]['fields'].append('post_text')
if get_setting('MULTISITE') and not self.has_restricted_sites(request):
2014-10-04 17:22:22 +00:00
fsets[1][1]['fields'][0].append('sites')
if request.user.is_superuser:
fsets[1][1]['fields'][0].append('author')
2016-06-23 07:57:08 +00:00
if apps.is_installed('djangocms_blog.liveblog'):
fsets[1][1]['fields'][2].append('enable_liveblog')
filter_function = get_setting('ADMIN_POST_FIELDSET_FILTER')
if callable(filter_function):
fsets = filter_function(fsets, request, obj=obj)
return fsets
def get_prepopulated_fields(self, request, obj=None):
return {'slug': ('title',)}
2014-01-04 16:07:09 +00:00
def save_model(self, request, obj, form, change):
2015-11-26 06:54:20 +00:00
obj._set_default_author(request.user)
2014-01-04 16:07:09 +00:00
super(PostAdmin, self).save_model(request, obj, form, change)
def get_queryset(self, request):
qs = super(PostAdmin, self).get_queryset(request)
sites = self.get_restricted_sites(request)
if sites.exists():
2016-05-22 10:08:39 +00:00
pks = list(sites.all().values_list('pk', flat=True))
2016-05-17 21:17:00 +00:00
qs = qs.filter(sites__in=pks)
return qs.distinct()
def save_related(self, request, form, formsets, change):
if self.get_restricted_sites(request).exists():
if 'sites' in form.cleaned_data:
form_sites = form.cleaned_data.get('sites', [])
removed = set(
self.get_restricted_sites(request).all()
).difference(form_sites)
diff_original = set(
form.instance.sites.all()
).difference(removed).union(form_sites)
form.cleaned_data['sites'] = diff_original
else:
2016-06-02 20:12:43 +00:00
form.instance.sites.add(
*self.get_restricted_sites(request).all().values_list('pk', flat=True)
)
super(PostAdmin, self).save_related(request, form, formsets, change)
class Media:
css = {
2015-09-19 23:11:14 +00:00
'all': ('%sdjangocms_blog/css/%s' % (settings.STATIC_URL, 'djangocms_blog_admin.css'),)
}
2015-09-19 23:11:14 +00:00
class BlogConfigAdmin(BaseAppHookConfig, TranslatableAdmin):
@property
def declared_fieldsets(self):
2016-02-25 07:36:16 +00:00
return self.get_fieldsets(None)
def get_fieldsets(self, request, obj=None):
2016-02-12 07:02:23 +00:00
"""
Fieldsets configuration
"""
return [
(None, {
2015-10-24 16:47:37 +00:00
'fields': ('type', 'namespace', 'app_title', 'object_name')
}),
('Generic', {
'fields': (
'config.default_published', 'config.use_placeholder', 'config.use_abstract',
'config.set_author',
)
}),
('Layout', {
'fields': (
'config.paginate_by', 'config.url_patterns', 'config.template_prefix',
'config.menu_structure', 'config.menu_empty_categories',
),
'classes': ('collapse',)
}),
('Notifications', {
'fields': (
'config.send_knock_create', 'config.send_knock_update'
),
'classes': ('collapse',)
}),
2015-10-31 00:19:24 +00:00
('Sitemap', {
'fields': (
'config.sitemap_changefreq', 'config.sitemap_priority',
),
'classes': ('collapse',)
}),
('Meta', {
'fields': (
'config.object_type',
)
}),
('Open Graph', {
'fields': (
'config.og_type', 'config.og_app_id', 'config.og_profile_id',
2015-08-22 20:35:30 +00:00
'config.og_publisher', 'config.og_author_url', 'config.og_author',
2015-10-18 11:01:00 +00:00
),
'description': _(
'You can provide plain strings, Post model attribute or method names'
)
}),
('Twitter', {
'fields': (
'config.twitter_type', 'config.twitter_site', 'config.twitter_author',
2015-10-18 11:01:00 +00:00
),
'description': _(
'You can provide plain strings, Post model attribute or method names'
)
}),
('Google+', {
'fields': (
'config.gplus_type', 'config.gplus_author',
2015-10-18 11:01:00 +00:00
),
'description': _(
'You can provide plain strings, Post model attribute or method names'
)
}),
]
2015-09-19 23:11:14 +00:00
def save_model(self, request, obj, form, change):
2016-04-19 21:02:02 +00:00
"""
Clear menu cache when changing menu structure
"""
if 'config.menu_structure' in form.changed_data:
from menus.menu_pool import menu_pool
menu_pool.clear(all=True)
return super(BlogConfigAdmin, self).save_model(request, obj, form, change)
2014-01-04 16:07:09 +00:00
admin.site.register(BlogCategory, BlogCategoryAdmin)
admin.site.register(Post, PostAdmin)
2015-09-19 23:11:14 +00:00
admin.site.register(BlogConfig, BlogConfigAdmin)