Django admin: отдельный просмотр и просмотр только для чтения
Я хотел бы использовать admin django для создания просмотра только для чтения объекта, который содержит кнопку "Изменить", которая переключает вас в обычный вид изменения того же объекта.
Я знаю, как использовать атрибуты readonly для создания представления только для чтения, но я не знаю, как создавать два представления, одно только для чтения и одно, что позволяет изменять.
Я бы хотел использовать как можно больше интерфейса администратора для этого, а не писать с нуля.
Обратите внимание, что этот вопрос касается не разрешений: у всех пользователей будет разрешение на изменение объектов. Просто я предпочел бы, чтобы они не использовали change_view, если они не намерены вносить изменения, уменьшая риск случайных изменений или одновременных изменений.
Ответы
Ответ 1
Вот ответ, который буквально делает то, что я просил только с несколькими строками кода и всего несколькими изменениями шаблонов:
class MyModelAdmin(admin.ModelAdmin):
fieldsets = [...]
def get_readonly_fields(self, request, obj=None):
if 'edit' not in request.GET:
return <list all fields here>
else:
return self.readonly_fields
Теперь обычный URL-адрес для change_form будет производить только переменную read-read, но если вы добавите "? edit = 1" к URL-адресу, вы сможете редактировать.
Шаблон change_form также может быть настроен в зависимости от того, находится ли URL?? edit = 1. Для этого поместите 'django.core.context_processors.request'
в TEMPLATE_CONTEXT_PROCESSORS
в settings.py
, а затем используйте request.GET.edit
в шаблоне.
Например, чтобы добавить кнопку "Редактировать", если не в режиме редактирования, вставьте
{% if not request.GET.edit %}
<li><a href="?edit=1">Edit</a></li>
{% endif %}
сразу после <ul class="object-tools">
в change_form.html
.
В качестве другого примера, изменив change_form.html
на
{% if save_on_top and request.GET.edit %}{% submit_row %}{% endif %}
будет означать, что строка отправки будет отображаться только в режиме редактирования. С помощью этого метода можно также скрыть кнопки "Удалить" на строках и т.д.
Для справки, вот что я ввел в settings.py
:
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.contrib.messages.context_processors.messages',
# Above here are the defaults.
'django.core.context_processors.request',
)
Ответ 2
Я предлагаю пересмотреть использование пользовательских представлений. С помощью generic DetailView
вам нужно написать буквально две строки кода. Шаблон также не потребует большой работы. Вы просто расширяете стандартный шаблон change_form.html, переопределяя блок field_sets
.
Я знаю, как использовать атрибуты readonly для создания представления только для чтения, но я не знаю, как создавать два представления, одно только для чтения и одно, что позволяет изменять.
Фактически вы можете зарегистрировать одну модель в администраторе дважды [1], используя прокси-модели. (Есть некоторые несоответствия с разрешениями для прокси-моделей, но это может быть не проблема в вашем случае.)
Кажется, возможно также зарегистрировать несколько сайтов-админов [2].
Я бы хотел использовать как можно больше интерфейса администратора для этого, а не писать с нуля.
Повторное использование интерфейса как таковое имеет мало общего с представлениями, в основном связанных с шаблонами и стилями. Однако просмотр должен предоставить контекст шаблона, необходимый для повторного использования интерфейса, как вы правильно указали.
Если вы решите пойти с несколькими представлениями на один ModelAdmin
, тогда вам может быть полезно проверить, как проект django-reversion
реализует интеграцию с администратором: reversion/admin.py.
Ссылки
Ответ 3
Вам понадобится изменить шаблон django admin для формы модели. Сделайте это только для чтения и добавьте кнопку в исходный шаблон, связанный с другим URL-адресом.
Примечание:
Я очень отговариваю этот подход, вы, безусловно, не будете препятствовать одновременным изменениям. Это должно быть разрешено с помощью блокировки.
Кроме того, я рекомендую использовать django-reversion для хранения истории объектов и устранения риска "случайных изменений".
Ответ 4
Вы можете создать собственное представление и отобразить там свой объект.
Чтобы создать пользовательский вид в модуле администратора, переопределите метод get_urls()
:
class MyAdmin(admin.ModelAdmin):
…
def get_urls(self):
urls = super(MyAdmin, self).get_urls()
my_urls = patterns('',
url(r'^custom_view/(?P<my_id>\d+)/$', self.admin_site.admin_view(self.custom_viem), name='custom_view')
)
return my_urls + urls
def custom_view(self, request, my_id):
"""Define your view function as usual in views.py
Link to this view using reverse('admin:custom_view')
"""
from myapp import views
return views.custom_view(request, my_id, self)
В views.py:
def custom_view(request, object_id, model_admin):
admin_site = model_admin.admin_site
opts = model_admin.model._meta
my_object = get_object_or_404(MyObject, pk=object_id)
# do stuff
context = {
'admin_site': admin_site.name,
'opts': opts,
'title': _('My custom view'),
'root_path': '%s' % admin_site.root_path,
'app_label': opts.app_label,
'my_object': my_object,
}
return render_to_response('my_template.html', context,
context_instance=RequestContext(request))
В своем шаблоне используйте {% extends "admin/base_site.html" %}
, чтобы сохранить внешний вид администратора.
Ответ 5
Нижеприведенный код представляет собой реализацию администратора только для чтения с использованием proxy models.
Models.py
//реальная модель
class CompetitionEntry(models.Model):
pass
//Прокси-модель
class ReviewEntry(CompetitionEntry):
class Meta:
proxy = True
def save(self, *args, **kwargs):
pass
admin.py
//редактируемый администратор
class CompetitionEntryAdmin(admin.ModelAdmin):
pass
admin.site.register(CompetitionEntry, CompetitionEntryAdmin)
//admin только для чтения (назначьте для этого только разрешение "изменить" )
class ReviewEntryAdmin(admin.ModelAdmin):
pass
admin.site.register(ReviewEntry, ReviewEntryAdmin)