You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

216 lines
9.3 KiB

# -*- coding: utf-8 -*-
import six
from django import get_version
from django.conf import settings
from django.contrib import admin
from django.contrib.admin.utils import model_format_dict
from django.db.models.fields import BLANK_CHOICE_DASH
from django.utils.timezone import template_localtime
from django_excel_response import ExcelResponse
from django_six import gettext_lazy as _
if not hasattr(settings, 'DJANGO_ADMIN_DISABLE_DELETE_SELECTED') or settings.DJANGO_ADMIN_DISABLE_DELETE_SELECTED:
# Django 2.x will raise error as below.
# TODO: Solution
#
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django_admin/__init__.py", line 3, in <module>
# from django_admin.djadmin import DeleteModelAdmin, ReadonlyModelAdmin, Readonly2ModelAdmin, ExportExcelModelAdmin, AdvancedExportExcelModelAdmin, ReadOnlyModelAdmin, ChangeOnlyModelAdmin, DeleteonlyModelAdmin, DeleteOnlyModelAdmin, AddOnlyModelAdmin, AdvancedActionsModelAdmin, SpecifiedQuantityQuerySetModelAdmin
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django_admin/djadmin.py", line 15, in <module>
# admin.site.disable_action('delete_selected')
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django/utils/functional.py", line 256, in inner
# self._setup()
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django/contrib/admin/sites.py", line 530, in _setup
# AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django/apps/registry.py", line 153, in get_app_config
# self.check_apps_ready()
# File "/Users/hqm/Envs/py37/lib/python3.7/site-packages/django/apps/registry.py", line 135, in check_apps_ready
# raise AppRegistryNotReady("Apps aren't loaded yet.")
# django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
if get_version()[0] == 1:
admin.site.disable_action('delete_selected')
class AdvancedActionsModelAdmin(object):
def get_action_choices(self, request, default_choices=BLANK_CHOICE_DASH):
"""
Return a list of choices for use in a form object. Each choice is a tuple (name, description).
"""
actions_exclude = self.actions_exclude if hasattr(self, 'actions_exclude') else []
choices = [] + default_choices
for func, name, description in six.itervalues(self.get_actions(request)):
if name in actions_exclude:
continue
choice = (name, description % model_format_dict(self.opts))
choices.append(choice)
return choices
class DeleteModelAdmin(object):
actions = ['override_delete_selected']
def override_delete_selected(modeladmin, request, queryset):
for query in queryset:
modeladmin.delete_model(request, query)
override_delete_selected.short_description = _(u'Delete selected %(verbose_name_plural)s')
class ExportExcelModelAdmin(object):
actions = ['export_excel']
def export_excel(modeladmin, request, queryset):
force_csv = (hasattr(settings, 'DJANGO_EXCEL_RESPONSE') and settings.DJANGO_EXCEL_RESPONSE) or (hasattr(modeladmin, 'force_csv') and modeladmin.force_csv)
return ExcelResponse(queryset, output_name=modeladmin.model._meta.verbose_name_plural, force_csv=force_csv)
export_excel.short_description = _(u'Export selected %(verbose_name_plural)s as Excel')
class AdvancedExportExcelModelAdmin(object):
actions = ['advanced_export_excel']
def excel_item(modeladmin, query, field):
foo_field = 'get_{0}_display'.format(field)
return str(getattr(query, foo_field)() if hasattr(query, foo_field) else template_localtime(getattr(query, field)))
def excel_data(modeladmin, request, query, model_fields, has_extra_excel_fields):
excel_item = [modeladmin.excel_item(query, field) for field in model_fields]
return excel_item + list(modeladmin.add_extra_excel_fields(request, query)) if has_extra_excel_fields else excel_item
def advanced_export_excel(modeladmin, request, queryset):
has_excel_headers = hasattr(modeladmin, 'excel_headers')
has_excel_headers_mapping = hasattr(modeladmin, 'excel_headers_mapping')
has_excel_fields = hasattr(modeladmin, 'excel_fields')
has_excel_fields_exclude = hasattr(modeladmin, 'excel_fields_exclude')
has_extra_excel_fields = hasattr(modeladmin, 'extra_excel_fields') # Add by call add_extra_excel_fields
model_fields = list(modeladmin.excel_fields) if has_excel_fields else [f.name for f in modeladmin.model._meta.fields]
if has_excel_fields_exclude:
model_fields = [field for field in model_fields if field not in set(modeladmin.excel_fields_exclude)]
excel_headers = modeladmin.excel_headers if has_excel_headers else (model_fields + list(modeladmin.extra_excel_fields) if has_extra_excel_fields else model_fields)
excel_headers = [(modeladmin.excel_headers_mapping.get(header) or header) for header in excel_headers] if has_excel_headers_mapping else excel_headers
excel_data = [excel_headers]
excel_data += [modeladmin.excel_data(request, query, model_fields, has_extra_excel_fields) for query in queryset]
force_csv = (hasattr(settings, 'DJANGO_EXCEL_RESPONSE') and settings.DJANGO_EXCEL_RESPONSE) or (hasattr(modeladmin, 'force_csv') and modeladmin.force_csv)
return ExcelResponse(excel_data, output_name=modeladmin.model._meta.verbose_name_plural, force_csv=force_csv)
advanced_export_excel.short_description = _(u'Advanced Export selected %(verbose_name_plural)s as Excel')
class ReadonlyModelAdmin(object):
""" Readonly for Update. """
def get_readonly_fields(self, request, obj=None):
if not hasattr(self, 'readonly_fields_exclude'):
self.readonly_fields_exclude = ()
if obj: # editing an existing object
return tuple(set(self.readonly_fields) | set(f.name for f in self.model._meta.fields) - set(self.readonly_fields_exclude))
return tuple(set(self.readonly_fields) - set(self.readonly_fields_exclude))
class Readonly2ModelAdmin(object):
""" Readonly for Add/Update. """
def get_readonly_fields(self, request, obj=None):
if not hasattr(self, 'readonly_fields_exclude'):
self.readonly_fields_exclude = ()
return tuple(set(self.readonly_fields) | set(f.name for f in self.model._meta.fields) - set(self.readonly_fields_exclude))
class ReadOnlyModelAdmin(ReadonlyModelAdmin):
""" Disables all editing capabilities. """
change_form_template = 'admin/readonly_form.html'
def __init__(self, *args, **kwargs):
super(ReadOnlyModelAdmin, self).__init__(*args, **kwargs)
def get_actions(self, request):
actions = super(ReadOnlyModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
def save_model(self, request, obj, form, change):
pass
def delete_model(self, request, obj):
pass
def save_related(self, request, form, formsets, change):
pass
class ChangeOnlyModelAdmin(object):
""" Disables add/delete capabilities. """
def get_actions(self, request):
actions = super(ChangeOnlyModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_add_permission(self, request):
return False
def has_delete_permission(self, request, obj=None):
return False
def delete_model(self, request, obj):
pass
class DeleteonlyModelAdmin(object):
""" Disables add/change capabilities. """
change_form_template = 'admin/deleteonly_form.html'
def has_add_permission(self, request):
return False
class DeleteOnlyModelAdmin(ReadonlyModelAdmin, DeleteonlyModelAdmin):
""" Disables add/change capabilities, fields readonly. """
class AddOnlyModelAdmin(ReadonlyModelAdmin):
""" Disables delete/change capabilities, fields readonly.. """
change_form_template = 'admin/addonly_form.html'
def __init__(self, *args, **kwargs):
super(AddOnlyModelAdmin, self).__init__(*args, **kwargs)
def get_actions(self, request):
actions = super(AddOnlyModelAdmin, self).get_actions(request)
if 'delete_selected' in actions:
del actions['delete_selected']
return actions
def has_delete_permission(self, request, obj=None):
return False
def delete_model(self, request, obj):
pass
class SpecifiedQuantityQuerySetModelAdmin(object):
""" Can Only Exist Specified Quantity QuerySet """
def save_model(self, request, obj, form, change):
# Change or Add
if change:
obj.save()
# Assign ``specified_quantity_queryset`` as 1 when ``specified_quantity_queryset`` not exists
if not hasattr(self, 'specified_quantity_queryset'):
self.specified_quantity_queryset = 1
# Assert whether ``specified_quantity_queryset`` is ``int`` or not
assert isinstance(self.specified_quantity_queryset, int)
if self.model.objects.count() >= self.specified_quantity_queryset:
return
obj.save()