Django: использовать запрос в качестве исходных данных модели

Я создаю интерфейс настроек, который работает путем сканирования папки настроек в установленных приложениях, сканирования файлов настроек и, наконец, сканирования для ModelForms.

Сейчас я на последнем шаге. Формы правильно найдены и загружены, но теперь мне нужно предоставить исходные данные. Исходные данные нужно вытащить из базы данных, и, как вы можете себе представить, он должен быть ограничен аутентифицированным пользователем (через request.user.id).

Имейте в виду, все это делается динамически. Ни одно из имен ни для чего, ни для их структуры известно в расширенном (я действительно не хочу поддерживать скучный интерфейс настроек).

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

class Set_Personal_Info(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ('nick_name', 'url')

Я посмотрел на modelformset_factory, который почти делает то, что я хочу сделать, но он работает только с результатами двух или более. (Здесь obj - одна из форм настроек)

Formset = modelformset_factory(obj.Meta.model, form=obj)
Formset(queryset=obj.Meta.model.objects.filter(id=request.user.id))

Я не могу фильтровать данные, я должен получить один и только один результат. К сожалению, я не могу использовать get()

Formset = modelformset_factory(obj.Meta.model, form=obj)
Formset(queryset=obj.Meta.model.objects.get(id=request.user.id))

"Пользовательский" объект не имеет атрибута "упорядочено"

Предоставление результата запроса, поскольку исходные данные также не работают, поскольку это не список.

Formset = modelformset_factory(obj.Meta.model, form=obj)
Formset(initial=obj.Meta.model.objects.get(id=request.user.id))

Объект пользователя не поддерживает индексирование

У меня такое чувство, что ответ прямо передо мной. Как я могу вытащить базу данных из базы данных и вставить ее в форму в качестве начальных значений?

Ответ 1

Я не уверен, что понимаю, что вы пытаетесь сделать - если вас интересует только одна форма, я не знаю, почему вы вообще участвуете в наборах форм.

Чтобы заполнить модельную форму исходными данными из базы данных, вы просто передаете аргумент экземпляра:

my_form = Set_Personal_Info(instance=UserProfile.objects.get(id=request.user.id))

Не забудьте также передать аргумент экземпляра при создании формы в POST, чтобы Django обновлял существующий экземпляр, а не создавал новый.

(Обратите внимание, что вы можете подумать о том, чтобы дать лучшие имена вашим объектам. obj обычно описывает экземпляр модели, а не форму, для которой form будет лучшим именем. И классы классов должны следовать за PEP8, и, вероятно, будет включать слово "форма", поэтому PersonalInfoForm будет хорошим именем.)

Ответ 2

Основываясь на том, что я понял... если вы хотите сгенерировать форму с динамическими полями, вы можете использовать это:

класс MyModelForm (forms.ModelForm):

def __init__(self, dynamic_fields, *args, **kwargs):
    super(MyModelForm, self).__init__(*args, **kwargs)

    self.fields = fields_for_model(self._meta.model, dynamic_fields, self._meta.exclude, self._meta.widgets)

    class Meta:
        model = MyModel

Где dynamic_fields - это кортеж.

Подробнее о динамических формах:

Также подход Daniel является действительным и чистым... На основе ваших разных идентификаторов/типов и т.д. вы можете использовать разные объекты формы

forms.py

класс MyModelFormA (forms.ModelForm):

class Meta:
    model = MyModel
    fields = ('field_a','field_b','field_c')
     class MyModelFormB(forms.ModelForm):

class Meta:
    model = MyModel
    fields = ('field_d','field_e','field_f')

views.py

если request.method == 'POST':

if id == 1:
    form = MyModelFormA(data=request.POST)
elif id == 2:
    form = MyModelFormB(data=request.POST)
else:
    form = MyModelFormN(data=request.POST)

if form.is_valid():
    form.save() else:
if id == 1:
    form = MyModelFormA()
elif id == 2:
    form = MyModelFormB()
else:
    form = MyModelFormN()