Подтвердить что ты не робот

Django admin: отдельный просмотр и просмотр только для чтения

Я хотел бы использовать admin django для создания просмотра только для чтения объекта, который содержит кнопку "Изменить", которая переключает вас в обычный вид изменения того же объекта.

Я знаю, как использовать атрибуты readonly для создания представления только для чтения, но я не знаю, как создавать два представления, одно только для чтения и одно, что позволяет изменять.

Я бы хотел использовать как можно больше интерфейса администратора для этого, а не писать с нуля.

Обратите внимание, что этот вопрос касается не разрешений: у всех пользователей будет разрешение на изменение объектов. Просто я предпочел бы, чтобы они не использовали change_view, если они не намерены вносить изменения, уменьшая риск случайных изменений или одновременных изменений.

4b9b3361

Ответ 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)