my admin.py:
class ExcelsAdmin(ExportActionModelAdmin):
save_on_top = True # выставляет кнопки для сохранения и редактирования в том месте где прописана данная строка
resource_class = ArticlesResource
list_display = ['id', 'contragent', 'delivery_address',
'region',
'label', 'packing',
'quantity', 'palletizing', 'output',
# 'output_at',
'date_output_at',
# 'time_output_at',
'price', 'is_signed', 'delivery_type',
# 'production_date',
'date_production_date',
# 'time_production_date',
'day_night', 'product_is_ready', 'pack_is_ready', 'packing_order',
# 'delivery_planed_at',
'date_delivery_planed_at',
# 'time_delivery_planed_at',
# 'send_at',
'date_send_at',
# 'time_send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take',
'date_date_take',
# 'time_date_take',
# 'created_at', 'modified_at',
'date_created_at',
'time_created_at',
'user',
'actual_project',
] # указывает какие поля в строке Заведенных заказов выводить к просмотру
# exclude = ('contragent',)# убирает из таблицы выбранное поле
fields = ['string_1', 'actual_project', 'id',
'date_created_at',
'time_created_at',
'user', 'contragent', 'delivery_address', 'region',
'label', 'packing',
'quantity', 'palletizing', 'output',
# 'output_at',
'date_output_at',
# 'time_output_at',
'price', 'is_signed', 'delivery_type', 'string_2',
# 'production_date',
'date_production_date',
# 'time_production_date',
'day_night', 'product_is_ready', 'pack_is_ready', 'string_3', 'packing_order',
# 'delivery_planed_at',
'date_delivery_planed_at',
# 'time_delivery_planed_at',
# 'send_at',
'date_send_at',
# 'time_send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take',
'date_date_take',
# 'time_date_take',
]
readonly_fields = ['actual_project', 'user', 'contragent', 'delivery_address', 'region',
'label', 'packing',
'quantity', 'palletizing', 'output',
'date_created_at',
'time_created_at',
# 'output_at',
'date_output_at',
# 'time_output_at',
'price', 'is_signed', 'delivery_type',
# 'production_date',
'date_production_date',
# 'time_production_date',
'day_night', 'product_is_ready', 'pack_is_ready', 'packing_order',
# 'delivery_planed_at',
'date_delivery_planed_at',
# 'time_delivery_planed_at',
# 'send_at',
'date_send_at',
# 'time_send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take'
'date_date_take',
# 'time_date_take',
] # данная команда делает ячейки таблицы только для чтения,
# но работает в паре с командой (fields) потому что без нее ячейки уходят вниз (в конец) под редактируемые ячейки.
list_display_links = ['id',
# 'created_at', 'modified_at',
'contragent', 'delivery_address', 'label', 'packing',
'quantity', 'palletizing', 'output',
# 'output_at',
'price', 'is_signed', 'delivery_type',
# 'production_date',
'day_night', 'product_is_ready', 'pack_is_ready', 'packing_order',
# 'delivery_planed_at',
# 'send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take'
] # указывает какие поля в строке Заведенных заказов позволяют ссылаться
# на заказ (заходить в заказ при нажатии на них)
search_fields = [
'contragent__title',
'delivery_address',
'region__title',
'label__title',
'transporter',
'user__username',
'number_ts',
] # дает возможность поиска в Админке по заданным в
# перечне полям, НО РАБОТАЕТ ТОЛЬКО С ТЕКСТОВЫМИ ПОЛЯМИ
# list_editable = ('n',) # показывает в каком поле можно вносить правки прямо в таблице
list_filter = [
# 'created_at',
'actual_project',
('date_created_at', DateRangeFilter),
('date_output_at', DateRangeFilter),
('date_production_date', DateRangeFilter),
('date_delivery_planed_at', DateRangeFilter),
('date_send_at', DateRangeFilter),
('date_date_take', DateRangeFilter),
('user', RelatedDropdownFilter),
('contragent', RelatedDropdownFilter),
('region', RelatedDropdownFilter),
('delivery_address', DropdownFilter),
('label', RelatedDropdownFilter),
('packing', RelatedDropdownFilter),
'palletizing', ] # показывает по каким полям будет выводиться поле фильтров (справа на экране)
manager_group_fields = ['actual_project',
# 'date_created_at',
# 'time_created_at',
'contragent', 'delivery_address', 'region',
'label', 'packing',
'quantity', 'palletizing', 'output',
# 'output_at',
'date_output_at',
# 'time_output_at',
'price', 'is_signed', 'delivery_type']
manager_and_transport_group_fields = ['actual_project',
# 'date_created_at',
# 'time_created_at',
'contragent', 'delivery_address', 'region',
'label', 'packing',
'quantity', 'palletizing', 'output',
# 'output_at',
'date_output_at',
# 'time_output_at',
'price', 'is_signed', 'delivery_type',
'packing_order',
# 'delivery_planed_at',
'date_delivery_planed_at',
# 'time_delivery_planed_at',
# 'send_at',
'date_send_at',
# 'time_send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take'
'date_date_take',
# 'time_date_take',
]
upakovka_group_fields = [
# 'user',# при налиции данной позиции есть возможность выставить нужного юзера,
# без данного поля все проставляется автоматически
# 'production_date',
'date_production_date',
# 'time_production_date',
'day_night', 'product_is_ready', 'pack_is_ready']
transport_group_fields = ['packing_order',
# 'delivery_planed_at',
'date_delivery_planed_at',
# 'time_delivery_planed_at',
# 'send_at',
'date_send_at',
# 'time_send_at',
'transporter', 'number_ts', 'price_fact',
# 'date_take'
'date_date_take',
# 'time_date_take',
]
transport_minus_all_group_fields = []
formfield_overrides = {
models.CharField: {'widget': Textarea(attrs={'size': 5, 'rows': 1, 'cols': 50})},
models.TextField: {'widget': Textarea(attrs={'rows': 4, 'cols': 40})},
models.IntegerField: {'widget': Textarea(attrs={'size': 5, 'rows': 1, 'cols': 50})},
# models.ForeignKey: {'widget': Textarea(attrs={'size': 5, 'rows': 1, 'cols': 50})},
}
# ------------------функция у superuser сохраняет строку "Действие" а у users убирает--------------
def get_actions(self, request):
actions = super(ExcelsAdmin, self).get_actions(request)
if not request.user.is_superuser:
actions = None
return actions
# ------------------------------------------------------------------------
def get_export_filename(self, request, queryset, file_format): # замена имени экспортированного файла
file = 'Vigruzka'
filename = "%s.%s" % (file,
file_format.get_extension())
# filename = filename.encode('utf-8')
return filename
# old_file = os.path.join("Users\11\Downloads", "Vigruzka.xlsx")
# new_file = os.path.join("Users\11\Downloads", "Выгрузка.xlsx")
# handle = open('config.conf', encoding='utf-8')
# os.rename(r"с:\Users\11\Downloads\Vigruzka.xlsx", r"с:\Users\11\Downloads\Выгрузка.xlsx")
# def save_model(self, request, obj, form, change): # Метод save_model отвечает за автозаполнение поля user.
# # Несколько несложных условий подставляют необходимый id пользователя.
# if form.is_valid():
# if not request.user.is_superuser or not form.cleaned_data['user']:
# obj.user = request.user
# obj.save()
# elif form.cleaned_data['user']:
# obj.user = form.cleaned_data['user']
# obj.save()
## ---------------------------------------------------
# данный вариант оставляет поле user редактируемым для пользователей
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
if not obj.user:
obj.user = request.user
obj.save()
# --------------------------------
# эксперимент
# def get_form(self, request, obj=None, **kwargs):
# form = super().get_form(request, obj, **kwargs)
# is_superuser = request.user.is_superuser
# if not is_superuser:
# form.User['user'].disabled = True
# return form
# ------------------------
def preprocess_list_display(self, request): # Метод preprocess_list_display добавляет колонку user в список
# объектов, если его просматривает администратор и удаляет колонку для обычных пользователей.
# Обратите внимание, что сперва мы проверяем, есть ли запись в list_display и если её нет,
# то добавляем, а потом уже смотрим кто просматривает список.
# При создании экземпляра EntryAdmin все его поля становятся глобальными для процесса,
# поэтому если мы удалим колонку list_display для обычного пользователя и не добавим для
# администратора, то администратор колонку не увидит. Именно поэтому мы каждый раз её вставляем в список.
if 'user' not in self.list_display:
self.list_display.insert(3, 'user')
if not request.user.is_superuser:
if 'user' in self.list_display:
self.list_display.remove('user') # удаляет столбец юзеров из просмотра юзера
# if 'group' in self.list_display:
# self.list_display.remove('group') # удаляет столбец группы из просмотра юзера
def pr(self, request): # добавляет в конце строки таблицы имя менеджера который создал строку
# (без возможности его редактирования)
if 'user' not in self.list_display:
self.list_display.insert(30, 'user')
def preprocess_search_fields(self, request): # Метод preprocess_search_fields делает тоже,
# что и preprocess_list_display, но только для search_fields. Фактически мы дали возможность
# администратору не только видеть автора записи, но и осуществлять поиск по его username.
if 'user__username' not in self.search_fields:
self.search_fields.insert(self.search_fields.__len__(), 'user__username')
if not request.user.is_superuser:
if 'user__username' in self.search_fields:
self.search_fields.remove('user__username')
def preprocess_list_filter(self, request): # убирает фильтр по contragent если пользователь не superuser
if ('contragent', RelatedDropdownFilter) not in self.list_filter:
# self.list_filter.insert(self.list_filter.__len__(), ('contragent', RelatedDropdownFilter))
self.list_filter.insert(2, ('contragent', RelatedDropdownFilter))
if not request.user.is_superuser:
if ('contragent', RelatedDropdownFilter) in self.list_filter:
self.list_filter.remove(('contragent', RelatedDropdownFilter))
# убирает фильтр по 'user' если пользователь не superuser и в группе managers
if ('user', RelatedDropdownFilter) not in self.list_filter:
self.list_filter.insert(1, ('user', RelatedDropdownFilter))
if not request.user.is_superuser and request.user.has_perm('excels.can_edit_manager_group'):
if ('user', RelatedDropdownFilter) in self.list_filter:
self.list_filter.remove(('user', RelatedDropdownFilter))
def changelist_view(self, request,
extra_context=None): # Три предыдущих метода вызываются из переопределенного changelist_view.
self.preprocess_list_display(request)
self.pr(request)
self.preprocess_search_fields(request)
self.preprocess_list_filter(request)
return super(ExcelsAdmin, self).changelist_view(request)
def get_readonly_fields(self, request, obj=None):
all_fields = list(self.get_fields(request, obj))
user_blocked_fields = all_fields[:]
iskom = 'Самовывоз'
naxodim = Articles.objects.filter(delivery_type__title__icontains=iskom)
if request.user.has_perm('excels.can_edit_manager_group'):
user_blocked_fields = [f for f in user_blocked_fields if f not in self.manager_group_fields]
if request.user.has_perm('excels.can_edit_upakovka_group'):
user_blocked_fields = [f for f in user_blocked_fields if f not in self.upakovka_group_fields]
if request.user.has_perm('excels.can_edit_transport_group'):
user_blocked_fields = [f for f in user_blocked_fields if f not in self.transport_group_fields]
# if request.user.has_perm('excels.can_edit_manager_group') and naxodim:
# user_blocked_fields = [f for f in user_blocked_fields if f not in self.manager_and_transport_group_fields]
#
# if request.user.has_perm('excels.can_edit_transport_group'):
# user_blocked_fields = [f for f in user_blocked_fields if f not in self.transport_minus_all_group_fields]
return user_blocked_fields
def get_queryset(self, request):
base_qs = super().get_queryset(request)
if request.user.has_perm('excels.can_edit_manager_group') and not (
request.user.has_perm('excels.can_edit_upakovka_group') or request.user.has_perm
('excels.can_edit_transport_group')):
return base_qs.filter(user=request.user)
return base_qs