Django: встроенный администратор формирует исходные данные для каждого экземпляра
Я читал много, но, похоже, я не могу найти решение.
Я пишу приложение в Django, я все еще пишу административную сторону.
У меня есть модель под названием "Среды" и модель под названием "Серверы", есть отношение ForeignKey между серверами и средами, например заданная среда имеет несколько серверов.
При изменении формы "добавить" для среды в интерфейсе администратора я использую форму Inline, чтобы иметь возможность визуализировать список серверов, которые будут связаны с средой, примерно так:
class ServerInline(admin.TabularInline):
model = Server
extra = 39
class EnvironmentAdmin(admin.ModelAdmin):
inlines = [ServerInline]
Довольно простое право?
Что бы я хотел сделать, это предварительно заполнить встроенные формы Сервера со значениями по умолчанию, я смог предварительно заполнить их тем же значением:
class ServerInlineAdminForm(forms.ModelForm):
class Meta:
model = Server
def __init__(self, *args, **kwargs):
super(ServerInlineAdminForm, self).__init__(*args, **kwargs)
self.initial['name']='Testing'
class ServerInline(admin.TabularInline):
form = ServerInlineAdminForm
model = Server
extra = 39
class EnvironmentAdmin(admin.ModelAdmin):
inlines = [ServerInline]
Но это не то, что я хочу, я хотел бы иметь возможность инициализировать экземпляры 39-й формы сервера с 39 различными значениями, которые у меня есть в списке. Какой был бы лучший способ сделать это?
Спасибо!
Ответы
Ответ 1
Я понял, что сам решил проблему и не ответил здесь.
Наконец, я решил переопределить метод save_model класса Environment для использования форм администратора.
Я объясню немного лучше:
У меня есть объект среды и объект сервера. В среде есть несколько серверов, которые связаны с ним через внешний ключ в объект сервера. Моя цель состояла в том, чтобы заполнить серверы, связанные с средой, в процессе создания среды. Чтобы сделать это, я сделал переопределение метода save_model для объекта Environment, создайте объекты obj.save() и AFTERWARDS для объектов Server, указывающих на эту среду, а затем снова obj.save(). Почему потом? Потому что я не могу связать новый созданный сервер со средой, которая еще не существует. Дайте мне знать, если кто-то заинтересован в фактическом коде.
Ответ 2
Вот моя реализация, благодаря Стивену за идею.
Все в admin.py:
class SecondaryModelInline(admin.ModelAdmin):
model = SecondaryModel
formset = SecondaryModelInlineFormSet
def get_formset(self, request, obj=None, **kwargs):
formset = super(SecondaryModelInline, self).get_formset(request, obj, **kwargs)
formset.request = request
return formset
def get_extra(self, request, obj=None, **kwargs):
extra = super(SecondaryModelInline, self).get_extra(request, obj, **kwargs)
something = request.GET.get('something', None)
if something:
extra = ... figure out how much initial forms there are, from the request ...
return extra
Где-то раньше, также в admin.py, это:
class SecondaryModelInlineFormSet(forms.models.BaseInlineFormSet):
model = SecondaryModel
def __init__(self, *args, **kwargs):
super(SecondaryModelInlineFormSet, self).__init__(*args, **kwargs)
if self.request.GET.get('something', None):
# build your list using self.request
self.initial=[{'field_a': 'A', ...}, {}... ]
Ответ 3
Не уверен, почему именно вы хотите это сделать, но, возможно, вы могли бы создать modelformset:
from django.forms.models import BaseModelFormSet
class ServerFormSet(BaseModelFormSet):
def __init__(self, *args, **kwargs):
super(ServerFormSet, self).__init__(*args, **kwargs)
self.initial = [{ 'name': 's1', }, {'name': 's2'},] # supply your list here
и установите это на своем inline:
class ServerInline(admin.TabularInline):
form = ServerInlineAdminForm
model = Server
extra = 39
formset = ServerFormSet
Я не пробовал это.
См:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.InlineModelAdmin.formset
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#providing-initial-values
https://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset
Ответ 4
Я не пробовал это, но поскольку дополнительные сформированные формы являются необходимыми Django Formsets, вам нужно связать исходные данные с набором форм, который объясняется в документах .
Я просто прочитал документы и, похоже, вы можете определить свой собственный набор форм внутри вашего inlineadmin, а затем, как упоминалось выше, предварительно заполнить набор форм с данными из вашего списка. Я думаю, вы могли бы добиться этого, поставив код предварительной обработки в свой класс init.
Я знаю, что это не очень подробное объяснение, но я нашел интересный вопрос и посмотрел документы и подумал, может быть, я мог бы указать вам в правильном направлении, с тем, что нужно делать дальше.
Ответ 5
Ну, я хотел прокомментировать ответ frnhr, но не имел достаточной репутации, поэтому:
Ответ работал у меня, мне просто нужно было пропустить формы в наборе форм и установить исходные данные для каждого из них:
class SecondaryModelInlineFormSet(forms.models.BaseInlineFormSet):
model = SecondaryModel
def __init__(self, *args, **kwargs):
super(SecondaryModelInlineFormSet, self).__init__(*args, **kwargs)
if self.request.GET.get('something', None):
# build your list using self.request
for form in self:
form.initial = {'field_a':'A',...} #This is what I changed
self.initial=[{'field_a': 'A', ...}, {}... ]
Ответ 6
Это сработало для меня в случае preopulating user
от request.user
для StackedInline
и TabularInline
.
def save_formset(self, request, form, formset, change):
for form in formset.forms:
form.instance.user = request.user
formset.save()