Измените поле формы 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()

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

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


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 }}


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 в представлении, но это дело вкуса.


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()

1

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

class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")

0

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.