Подтвердить что ты не робот

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 различными значениями, которые у меня есть в списке. Какой был бы лучший способ сделать это?

Спасибо!

4b9b3361

Ответ 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()