Одна из функций проекта Django, который я пишу, - это отправка информационного бюллетеня. У меня есть модель Newsletter и функция send_newsletter, которые я зарегистрировал для прослушивания сигнала Newsletter от post_save. Когда объект информационного бюллетеня сохраняется через интерфейс администратора, send_newsletter проверяет, имеет ли значение created значение True, и если да, он действительно отправляет письмо.
Однако редактировать уже отправленный информационный бюллетень не имеет особого смысла по очевидным причинам. Есть ли способ сделать объект Newsletter доступным только для чтения после того, как он был сохранен?
Я знаю, что могу переопределить метод save объекта, чтобы вызвать ошибку или ничего не делать, если объект существует. Однако я не вижу в этом смысла. Что касается первого, я не знаю, где отловить эту ошибку и как сообщить пользователю о том, что объект не был сохранен. Что касается последнего, то предоставление пользователю ложной обратной связи (интерфейс администратора сообщает, что сохранение выполнено успешно) не похоже на хорошее дело.
Что я действительно хочу, так это позволить пользователю использовать интерфейс администратора для написания информационного бюллетеня и его отправки, а затем просматривать информационные бюллетени, которые уже были отправлены. Я хотел бы, чтобы интерфейс администратора отображал данные для отправленных информационных бюллетеней в нередактируемом поле ввода без кнопки «Сохранить». В качестве альтернативы я бы хотел, чтобы кнопка «Сохранить» была неактивной.






Вы можете проверить, создается он или обновляется, в методе модели save:
def save(self, *args, **kwargs):
if self.pk:
raise StandardError('Can\'t modify bla bla bla.')
super(Payment, self).save(*args, **kwargs)
Приведенный выше код вызовет исключение, если вы попытаетесь сохранить существующий объект. Для объектов, которые ранее не сохранялись, не заданы первичные ключи.
Предлагаемое чтение: Дзен Админа в глава 17 книги Джанго.
Резюме: администратор не предназначен для того, что вы пытаетесь сделать :(
Однако версия книги 1.0 охватывает только Django 0.96, и с тех пор произошло хорошее.
В Django 1.0 админка сайта более настраиваемый. Поскольку я сам не настраивал администратора, мне придется угадывать, основываясь на документации, но я бы сказал, что переопределение формы модели - ваш лучший выбор.
используйте readonlyadmin в ur amdin.py. Перечислите все поля, которые вы хотите сделать только для чтения. После создания объекта вы не можете редактировать их, а затем
используйте ссылку
http://www.djangosnippets.org/snippets/937/
скопируйте файл, а затем импортируйте в ur admin.py и используйте его
Что вы можете легко сделать, так это сделать все поля доступными только для чтения:
class MyModelAdmin(ModelAdmin):
form = ...
def get_readonly_fields(self, request, obj=None):
if obj:
return MyModelAdmin.form.Meta.fields
else: # This is an addition
return []
Что касается исчезновения сохранения, было бы намного проще, если бы
has_change_permission, возвращающий False, не отключит даже отображение формыadmin_modify.submit_row), не будет использовать show_save=True безоговорочно.В любом случае, один из способов заставить этого парня не отображаться:
Создайте альтернативную версию has_change_permission с правильной логикой:
class NoSaveModelAdminMixin(object):
def render_change_form(self, request, context, add=False, change=False, form_url='', obj=None):
response = super(NoSaveModelAdmin, self).render_change_form(request, context, add, change,form_url, obj)
response.context_data["has_change_permission"] = self.has_real_change_permission(request, obj)
def has_real_change_permission(self, request, obj):
return obj==None
def change_view(self, request, object_id, extra_context=None):
obj = self.get_object(request, unquote(object_id))
if not self.has_real_change_permission(request, obj) and request.method == 'POST':
raise PermissionDenied
return super(NoSaveModelAdmin, self).change_view(request, object_id, extra_context=extra_context)
Замените тег шаблона submit_row следующим образом:
@admin_modify.register.inclusion_tag('admin/submit_line.html', takes_context=True)
def submit_row(context):
...
'show_save': context['has_change_permission']
...
admin_modify.submit_row = submit_row