Получить поле формы Django из поля модели - PullRequest
15 голосов
/ 06 апреля 2010

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

Я бы хотел создать поле формы без жесткого кодирования типа полей модели.

Я знаю, что могу получить поле формы из поля модели, используя model_field.formfield(). Но как я могу получить конкретное поле модели?

Мое первое решение:

def get_fields(model_class):
    fields = {}
    for f in model_class._meta.fields:
        fields[f.name] = f

class MyForm(forms.Form):
    foo_name = get_fields(Foo)['name'].formfield()
    bar_name = get_fields(Bar)['name'].formfield()
    other_field = ...

Есть ли уже эквивалент get_fields? Это плохая идея? Мне неудобно полагаться на атрибут модели _meta. Или я иду по этому совершенно неправильному пути?

Ответы [ 4 ]

14 голосов
/ 06 апреля 2010

Вы также можете взглянуть на django.forms.models.fields_for_model. Это должно дать вам словарь полей, а затем вы можете добавить поля формы

10 голосов
/ 06 апреля 2010

Вам никогда не придется создавать поля самостоятельно, если вы не хотите особого поведения.

Это должно быть так же просто, как использовать два ModelForm s и дополнительный Form внутри одного тега <form> в шаблоне с одной кнопкой отправки.

в forms.py:

class Model1Form(forms.ModelForm):
    class Meta:
        model = Model1
        fields = ('fields', 'you', 'want')

class Model2Form(forms.ModelForm):
    class Meta:
        model = Model2
        fields = ('fields', 'you', 'want')

class ExtraFieldsForm(forms.Form):
    extra_field = form.TextField() # or whatever field you're looking for

в views.py:

form1 = Model1Form(request.POST or None)
form2 = Model2Form(request.POST or None)
form3 = ExtraFieldsForm(request.POST or None)

if form1.is_valid() and form2.is_valid() and form3.is_valid():
    form1.save()
    form2.save()
    form3.save()

    ...do other stuff like a redirect...

и в шаблоне:

<form method="POST" action="">{% csrf_token %}
    <fieldset>
        {{ form1|as_uni_form }}
        {{ form2|as_uni_form }}
        {{ form3|as_uni_form }}
        <div class="form_block">
            <input type="submit" value="Save both models"/>
        </div>
    </fieldset>
</form>

Я привык использовать django-uni-form, но вы можете отображать поля формы так, как вам нравится. Удачи на вашем сайте.

6 голосов
/ 28 января 2016

В настоящее время существует документированный API для получения поля модели из класса модели:

my_model_field = MyModel._meta.get_field('my_model_field_name')

Хотя это официально не документировано до Django 1.8, это должно работать и с более ранними версиями Django.

Получив это, вы можете получить поле формы следующим образом:

form_field = my_model_field.formfield()
2 голосов
/ 14 апреля 2012

Другим решением может быть создание одной 'uber-формы, которая объединяет конкретные модели моделей. Форма поддерживает методы, которые форма обычно предоставляет, и передает их всем дочерним формам. Некоторые будут простыми, другие сложными. Большим преимуществом этого подхода является то, что на него не влияет ни один код, кроме формы (код проверки клиента и т. Д.). Концепция не очень революционная, но я думаю, что сложнее добавить потом. Пол

...