2014-11-11 5 views
3

Я пытаюсь создать полностью динамическую форму в admin django. Найдено раствор в goole, например this и this. Но это решение не работает для меня. Например, этот код:Django 1.7, dynamic administrator form

class DeviceAdmin(admin.ModelAdmin): 
    form = MyDeviceAdminForm 
    def get_fieldsets(self, request, obj=None): 
     fieldsets = super(DeviceAdmin, self).get_fieldsets(request, obj) 
     fieldsets[0][1]['fields'] += ('foo',) 
     return fieldsets 

class MyDeviceAdminForm(forms.ModelForm): 
    class Meta: 
     model = Device 
    def __init__(self, *args, **kwargs): 
     super(MyDeviceAdminForm, self).__init__(*args, **kwargs) 
     self.fields['foo'] = forms.IntegerField(label="foo") 

получил эту ошибку: "Неизвестное поле (s) (item_type), указанную для устройства Проверьте поля/fieldsets/исключить атрибуты класса DeviceAdmin."

И я не могу найти решение для этого. Я понимаю, что мне нужно определить в каком-то другом месте foo поле, но не знает где.

+0

Необходимо указать, какие поля использовать или исключать те, которые вы не хотите использовать: https: // docs.djangoproject.com/ru/dev/topics/forms/modelforms/#selecting-the-fields-to-use – rnevius

+0

@rnevius спасибо! Но я не могу этого сделать, потому что я не знаю, что подал имена, чтобы установить его явно в Meta ModelForm. Это моя проблема - я хочу сгенерировать некоторые поля в зависимости от исходного поля. И я не могу объявить их в методе ModelForm __init__, потому что для ModelAdmin это слишком поздно, и последняя страница html будет отсутствовать. – valex

ответ

1

Django> 1.4 внес изменения, которые вызывают этот полом. В основном get_fieldsets вызывается перед фабрикой форм, а затем фабрика жалуется на дополнительное поле, которое вы вводите в get_fieldsets. К счастью, get_fieldsets вызывается более одного раза, что дает возможность подорвать поток. Мое решение состоит в том, чтобы добавить атрибут маркера к запросу при его прохождении через механизм формы:

def get_fieldsets(self, request, obj=None): 
    fieldsets = super(DeviceAdmin, self).get_fieldsets(request, obj) 
    if hasattr(request, "_gfs_marker"): 
     fieldsets[0][1]['fields'] += ('foo',) 
    setattr(request, "_gfs_marker", 1) 
    return fieldsets 
+0

Я в той же ситуации, и, к сожалению, я не понимаю, как вам это удается. Не могли бы вы объяснить немного дальше? – mufasa

+0

@mufasa, ModelAdmin теперь вызывает 'get_fieldsets()' дважды, один раз перед тем, как форма будет инициализирована. Если у вас есть пользовательская форма, чья '__init __()' определяет настраиваемые поля, то первый вызов 'get_fieldsets()' будет вызывать эту ошибку, поскольку, насколько это известно, любые ссылки на ваши настраиваемые поля являются недействительными. Это исправление удаляет все пользовательские поля для первого вызова, но добавляет их ко второму, после того как они определены. Это немного взломать, но, к сожалению, это единственный способ поддерживать пользовательские поля форм в Django admin. – Cerin

0

Если это просто имя поля видимое для пользователя, который вы хотите изменить (название внутреннего поля не будет видно в любом случае), вы можете использовать фабрику классов:

def get_MyDeviceAdminForm(field_name): 
 
    class MyDeviceAdminForm(forms.ModelForm): 
 
     my_new_field_internal = forms.CharField(label=field_name) 
 
     class Meta: 
 
      model = InfoLog 
 
    return MyDeviceAdminForm 
 
class DeviceAdmin(admin.ModelAdmin): 
 
    form = get_MyDeviceAdminForm("Verbose name of the new field")

Это работает в Django 1.6.

+0

Спасибо, но здесь вы определяете дополнительное поле статически, и мне нужно определить их динамически, имена и начальные значения определяются базовыми полями. И поскольку я обнаружил, что администратор django не может этого сделать. Поэтому я просто пишу свое собственное мнение. Большое спасибо! – valex