Администратор Django: исключить поле только в форме изменений - PullRequest
8 голосов
/ 07 августа 2009

Если есть способ определить, добавляется или изменяется информация в модели.

Если есть возможность, эту информацию можно использовать для исключения полей.

Какой-то псевдокод для иллюстрации того, о чем я говорю.

class SubSectionAdmin(admin.ModelAdmin):
    if something.change_or_add = 'change':
        exclude = ('field',)
    ...

Спасибо

Ответы [ 4 ]

15 голосов
/ 16 июня 2011

ответ orwellian заставит весь синглтон SubSectionAdmin изменить свойство exclude.

Чтобы исключить поля для каждого запроса, нужно выполнить что-то вроде:

class SubSectionAdmin(admin.ModelAdmin):
    # ...
    def get_form(self, request, obj=None, **kwargs):
        """Override the get_form and extend the 'exclude' keyword arg"""
        if obj:
            kwargs.update({
                'exclude': getattr(kwargs, 'exclude', tuple()) + ('field',),
            })
        return super(SubSectionAdmin, self).get_form(request, obj, **kwargs)

, который просто сообщит Форме, чтобы исключить эти дополнительные поля.

Не уверен, как это будет вести себя, если исключить обязательное поле ...

7 голосов
/ 02 декабря 2016

Установка self.exclude делает так, как упоминает @ steve-pike, заставить целое SubSectionAdmin singleton изменить свое свойство exclude. Singleton - это класс, который будет повторно использовать один и тот же экземпляр каждый раз, когда создается экземпляр класса, поэтому экземпляр создается только при первом использовании конструктора, а последующее использование конструктора возвращает тот же экземпляр. Смотрите вики-страницу для более подробного описания. Это означает, что если вы напишите код для исключения поля при изменении, это будет означать, что если вы впервые добавите элемент, поле будет там, но если вы откроете элемент для изменения, поле будет исключено для следующих посещений. на страницу добавления.

Простейший способ добиться поведения для каждого запроса - использовать get_fields и проверить аргумент obj, который равен None, если мы добавляем объект, и экземпляр объекта, если мы меняемся. объект. Метод get_fields доступен в Django 1.7.

class SubSectionAdmin(admin.ModelAdmin):
    def get_fields(self, request, obj=None):
        fields = super(SubSectionAdmin, self).get_fields(request, obj)
        if obj:  # obj will be None on the add page, and something on change pages
            fields.remove('field')
        return fields

Обновление:

Обратите внимание, что get_fields может возвращать кортеж, поэтому вам может потребоваться преобразовать fields в список для удаления элементов. Вы также можете столкнуться с ошибкой, если имя поля, которое вы пытаетесь удалить, отсутствует в списке. Поэтому в некоторых случаях, когда у вас есть другие факторы, исключающие поля, может быть лучше создать набор исключений и удалить их, используя понимание списка:

class SubSectionAdmin(admin.ModelAdmin):
    def get_fields(self, request, obj=None):
        fields = list(super(SubSectionAdmin, self).get_fields(request, obj))
        exclude_set = set()
        if obj:  # obj will be None on the add page, and something on change pages
            exclude_set.add('field')
        return [f for f in fields if f not in exclude_set]

В качестве альтернативы вы также можете получить deepcopy результата в методе get_fieldsets, который в других случаях может дать вам доступ к лучшему контексту для исключения вещей. Очевидно, это будет полезно, если вам нужно действовать с именем набора полей. Кроме того, это единственный путь, если вы действительно используете fieldsets , так как при этом вызов на get_fields.

будет опущен.
from copy import deepcopy

class SubSectionAdmin(admin.ModelAdmin):
    def get_fieldsets(self, request, obj=None):
        """Custom override to exclude fields"""
        fieldsets = deepcopy(super(SubSectionAdmin, self).get_fieldsets(request, obj))

        # Append excludes here instead of using self.exclude.
        # When fieldsets are defined for the user admin, so self.exclude is ignored.
        exclude = ()

        if not request.user.is_superuser:
            exclude += ('accepted_error_margin_alert', 'accepted_error_margin_warning')

        # Iterate fieldsets
        for fieldset in fieldsets:
            fieldset_fields = fieldset[1]['fields']

            # Remove excluded fields from the fieldset
            for exclude_field in exclude:
                if exclude_field in fieldset_fields:
                    fieldset_fields = tuple(field for field in fieldset_fields if field != exclude_field)  # Filter
                    fieldset[1]['fields'] = fieldset_fields  # Store new tuple

        return fieldsets
6 голосов
/ 18 сентября 2009
class SubSectionAdmin(admin.ModelAdmin):
    # ...
    def change_view(self, request, object_id, extra_context=None):       
        self.exclude = ('field', )
        return super(SubSectionAdmin, self).change_view(request, object_id, extra_context)
0 голосов
/ 07 ноября 2011

Подход ниже имеет то преимущество, что не переопределяет свойство объекта exclude; вместо этого он сбрасывается на основе каждого типа запроса

class SubSectionAdmin(admin.ModelAdmin):
    add_exclude = ('field1', 'field2')
    edit_exclude = ('field2',)

    def add_view(self, *args, **kwargs):
        self.exclude = getattr(self, 'add_exclude', ())
        return super(SubSectionAdmin, self).add_view(*args, **kwargs)

    def change_view(self, *args, **kwargs):
        self.exclude = getattr(self, 'edit_exclude', ())
        return super(SubSectionAdmin, self).change_view(*args, **kwargs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...