Как динамически манипулировать полями формы в Django в ModelAdmin? - PullRequest
3 голосов
/ 21 мая 2011

У меня есть поле (slug), которое «требуется» в модели, но я хочу изменить поле в классе ModelAdmin на необязательное. Если пользователь не заполняет его, оно автоматически заполняется другим полем (именем).

class SomeModel(model.Model):
  name = model.CharField(max_length=255)
  slug = model.SlugField(unique=True, max_length=255)

Я пытался сделать это различными способами, такими как переопределение get_form () внутри ModelAdmin или использование класса ModelForm и конкретное указание формы.

class SomeModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(self.__class__, self).get_form(request, obj, **kwargs)
        form.slug.required = False
        return form

Однако ни одно из решений не сработало для меня. Помимо ручного создания формы, есть ли другое более быстрое решение?

У меня много таких форм, и делать это вручную может быть утомительно и трудно поддерживать.

Ответы [ 3 ]

4 голосов
/ 06 июля 2012

Нашел эту страницу через Google, когда боролся с той же проблемой сам.Следующее также будет работать в ModelAdmin:

def get_form(self, *args, **kwargs):
    form = super(SomeModelAdmin, self).get_form(*args, **kwargs)
    form.base_fields['slug'].required = False
    return form

В последующих формах, созданных из обновленного ModelFormMetaclass, поле slug будет необязательным.

Это лучше работает в моей ситуации, когда у меня есть только один класс, в котором мне нужно запросить поле, и не нужно выполнять какие-либо преобразования данных при сохранении.Решение GoogleDroid лучше, если у вас много классов, или если необходимы преобразования данных.

1 голос
/ 21 мая 2011

В вашем get_form методе form.fields['slug'].required должно работать.

Но правильный способ сделать это - просто предоставить пользовательскую ModelForm.

class SomeModelForm(forms.ModelForm):
    slug = forms.CharField(required=False)

class SomeModelAdmin(admin.ModelAdmin):
    form = SomeModelForm

Кстати, не делайте super(self.__class__, self). Вы всегда должны явно указывать имя текущего класса при использовании super, в противном случае любой подкласс, который наследуется от вашего и в свою очередь вызывает super, сломается.

Редактировать form.fields, а не forms.fields.

Говоря self.__class__, вы явно мешаете Python отрабатывать наследование - потому что оно всегда ссылается на конкретный класс - то есть на нижнюю часть дерева наследования. Но если ваш метод является серединой этого дерева, то ссылка на конкретный класс в super неверна - потому что вы хотите, чтобы он вызывал следующий уровень вверх, а не один снизу вверх. Вот почему вы всегда должны называть класс, в котором вы находитесь - в данном случае, super(SomeModelAdmin, self).

0 голосов
/ 26 мая 2011

Я просто хотел сообщить об этом на случай, если другие могут найти это полезным.

Я никогда не смог в get_form методе сделать form.fields['slug'].required и так и не понял почему. Однако я решил свою проблему, создав новую форму, унаследованную от ModelForm.

Мне пришлось переопределить init (), чтобы установить self.fields['slug'].required = False после вызова родительского конструктора, затем переопределить clean_slug(), чтобы изменить содержимое поля слагов, если требуется, путем доступа к self.data['slug'].

Надеюсь, это кому-нибудь поможет

...