разные поля для добавления и изменения страниц в админке

У меня есть приложение django со следующим классом в моем admin.py:


Я хочу, чтобы эти поля были для страницы добавления, но другие поля для страницы изменения. Как я могу это сделать?

21
задан Serjik 19 December 2015 в 10:22
поделиться

4 ответа

Сначала взглянем на источник методов класса get_form и get_formsets класса ModelAdmin, расположенных в django.contrib.admin.options.py. Вы можете переопределить эти методы и использовать kwargs, чтобы получить желаемое поведение. Например:

class SoftwareVersionAdmin(ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        # Proper kwargs are form, fields, exclude, formfield_callback
        if obj: # obj is not None, so this is a change page
            kwargs['exclude'] = ['foo', 'bar',]
        else: # obj is None, so this is an add page
            kwargs['fields'] = ['foo',]
        return super(SoftwareVersionAdmin, self).get_form(request, obj, **kwargs)
27
ответ дан 29 November 2019 в 06:23
поделиться

Я не мог заставить это работать в django 1.6.5, используя вышеупомянутые решения. Поэтому я попытался создать формы и заставить get_form обслуживать эти заранее определенные формы в зависимости от того, существует объект или нет:

models.py:

from django.db import models

class Project(models.Model):
    name = models.CharField('Project Name', max_length=255)
    slug = models.SlugField('Project Slug', max_length=255, unique=True)

forms.py: из форм импорта django из импорта моделей Project

class ProjectAddForm(forms.ModelForm):

    test = forms.Field()

    class Meta:
        model = Project


class ProjectEditForm(forms.ModelForm):

    class Meta:
        model = Project
        fields = ("name", 'slug')

admin.py

from django.contrib import admin
from models import Project
from forms import ProjectAddForm, ProjectEditForm


class ProjectAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        # Proper kwargs are form, fields, exclude, formfield_callback
        if obj:
            self.form = ProjectEditForm
        else:
            self.form = ProjectAddForm
        return super(ProjectAdmin, self).get_form(request, obj, **kwargs)


admin.site.register(Project, ProjectAdmin)

Теперь я могу перехватить непостоянное тестовое поле в чистых формах и делать с ним все, что захочу, просто перезаписав clean в ProjectAddForm:

def clean(self):
    cleaned_data = super(ProjectAddForm, self).clean()
    test = cleaned_data.get("test")
    # Do logic here
    #raise forms.ValidationError("Passwords don't match.")
    return cleaned_data
5
ответ дан 29 November 2019 в 06:23
поделиться

Этот конкретный код не работал для меня. Я просто немного меняю это:

if obj: # obj is not None, so this is a change page
        #kwargs['exclude'] = ['owner']
        self.fields = ['id', 'family_name', 'status', 'owner']
    else: # obj is None, so this is an add page
        #kwargs['fields'] = ['id', 'family_name', 'status']
        self.fields = ['id', 'family_name', 'status']
    return super(YourAdmin, self).get_form(request, obj, **kwargs)
2
ответ дан 29 November 2019 в 06:23
поделиться

dpawlows 'решение, представленное выше, я думаю, самое ясное.

Однако, я столкнулся с дополнительной проблемой в структуре такого типа.

Если change_view() вносит изменения в модель, например, указывает readonly_fields, которые были заполнены в add_view(), эти изменения сохраняются в add_view() после вызова change_view(). Например:

def add_view(self, request, extra_context=None):
    return super().add_view(request)

def change_view(self, request, object_id, extra_context=None):
    self.readonly_fields = ['name']  # this change persists in add_view()
    return super().change_view(self, request, object_id)

В этом случае, после вызова change_view() для любого экземпляра, вызов add_view() покажет readonly_fields (в данном случае «имя»), установленное как change_view() и, таким образом, защитить эти поля от заполнения.

Эту проблему можно решить, добавив назначение «откат» в add_view():

def add_view(self, request, extra_context=None):
    self.readonly_fields = []  # 'roll back' for changes made by change_view()
    return super().add_view(request)
2
ответ дан 29 November 2019 в 06:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: