Измените поле формы Django на скрытое поле

128

У меня есть форма Django с RegexField , которая очень похожа на обычное поле ввода текста.

На мой взгляд, при определенных условиях я хочу скрыть это от пользователя и стараюсь сохранить форму как можно более похожей. Как лучше всего превратить это поле в HiddenInputполе?

Я знаю, что могу установить атрибуты в поле с помощью:

form['fieldname'].field.widget.attr['readonly'] = 'readonly'

И я могу установить желаемое начальное значение с помощью:

form.initial['fieldname'] = 'mydesiredvalue'

Однако это не изменит форму виджета.

Какой самый лучший / самый "django-y" / наименее "хакерский" способ сделать это поле <input type="hidden">полем?

Рори
источник

Ответы:

169

Если у вас есть собственный шаблон и представление, вы можете исключить поле и использовать его {{ modelform.instance.field }}для получения значения.

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

form.fields['field_name'].widget = forms.HiddenInput()

но я не уверен, что это защитит метод сохранения при публикации.

Надеюсь, поможет.

christophe31
источник
1
&quot;&quot; is not a valid value for a primary key.После использования этого решения я получаю a в методе is_valid.
Йенс Тиммерман
Звучит странно. Я думаю, это связано с чем-то другим: вы показываете как HiddenInput первичный ключ объектов, которые вы создаете? Если да, то не стоит.
christophe31
Возможно, это само собой разумеется, но вам нужно будет импортировать формы, прежде чем это заработает. from django import forms
teewuane
2
в hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())версии 1.7 используйте этот синтаксис: где ключ - это новый синтаксис виджета в конце. Настройте под свои нужды.
Marc
196

Это также может быть полезно: {{ form.field.as_hidden }}

semente
источник
3
Это лучший ответ ИМХО. Я всегда ненавидел использовать свой "контроллерный" код Python для определения отображения поля формы.
trpt4him
Я часто делаю общий шаблон формы с crispyforms. Если вы используете crispyforms или отображаете поля в простом цикле forloop, потому что вам нужна структура формы в своем классе формы, переопределение виджета в форме - хороший способ сделать это. Но, если вы управляете рендерингом формы в своем шаблоне, действительно, это решение намного яснее / понятнее.
christophe31
Стоит отметить, что это, похоже, стирает все классы, которые вы заранее применили к полю ...
Джон Аарон,
59

вариант, который сработал для меня, определите поле в исходной форме как:

forms.CharField(widget = forms.HiddenInput(), required = False)

тогда, когда вы переопределите его в новом классе, он сохранит свое место.

Шай Рыбак
источник
45

Во-первых, если вы не хотите, чтобы пользователь изменял данные, то будет проще просто исключить поле. Включение его в качестве скрытого поля просто добавляет больше данных для отправки по сети и предлагает злоумышленнику изменить его, когда вы этого не хотите. Если у вас есть веская причина включить поле, но скрыть его, вы можете передать ключевое слово arg в конструктор модели. Возможно что-то вроде этого:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
    def __init__(self, *args, **kwargs):
        from django.forms.widgets import HiddenInput
        hide_condition = kwargs.pop('hide_condition',None)
        super(MyModelForm, self).__init__(*args, **kwargs)
        if hide_condition:
            self.fields['fieldname'].widget = HiddenInput()
            # or alternately:  del self.fields['fieldname']  to remove it from the form altogether.

Тогда, на ваш взгляд:

form = MyModelForm(hide_condition=True)

Я предпочитаю этот подход к изменению внутренних компонентов modelform в представлении, но это дело вкуса.

rych
источник
11
просто совет: kwargs.pop ('hide_condition', False) вместо kwargs ['hide_condition']. вы будете обрабатывать случай no arg, иметь значение по умолчанию и del одновременно.
christophe31
2
спасибо за подсказку, christophe31. Я обновил ваше предложение, так как оно делает код более понятным.
rych 01
1
Можно ли при таком подходе полностью скрыть поле? Как если бы вы пошли class Meta: exclude = ["fieldname"]. Проблема здесь в том, что мета-подход «статичен», но мне нужно что-то динамическое. См stackoverflow.com/questions/20243735/...
Themerius
You cab di def __init __ (self, hide_condition = True, * args, ** kwargs), который является самым чистым способом ...
Визгеан Скелору,
22

Для нормальной формы вы можете сделать

class MyModelForm(forms.ModelForm):
    slug = forms.CharField(widget=forms.HiddenInput())

Если у вас есть модельная форма, вы можете сделать следующее

class MyModelForm(forms.ModelForm):
    class Meta:
        model = TagStatus
        fields = ('slug', 'ext')
        widgets = {'slug': forms.HiddenInput()}

Вы также можете переопределить __init__метод

class Myform(forms.Form):
    def __init__(self, *args, **kwargs):
        super(Myform, self).__init__(*args, **kwargs)
        self.fields['slug'].widget = forms.HiddenInput()
anjaneyulubatta505
источник
1

Если вы хотите, чтобы поле всегда было скрыто, используйте следующее:

class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")
Zags
источник
0

Вы можете просто использовать css:

#id_fieldname, label[for="id_fieldname"] {
  position: absolute;
  display: none
}

Это сделает поле и его метку невидимыми.

user20310
источник