[Django]-Rendering a value as text instead of field inside a Django Form

22👍

<form>
    {% for field in form %}
            {{ field.label }}: {{ field.value }}
    {% endfor %}
</form>

Take a look here Form fields and Working with forms

👤tefozi

19👍

Old topic, but I think some people still comes here.

You can do something like this too:

from django.utils.safestring import mark_safe

class PlainTextWidget(forms.Widget):
    def render(self, _name, value, _attrs):
        return mark_safe(value) if value is not None else '-'

And in your form

class SomeForm(Form):
   somename = forms.CharField(widget=PlainTextWidget)

Under Django 2.1+ you’ll need the following:

from django.utils.safestring import mark_safe

class PlainTextWidget(forms.Widget):
    def render(self, name, value, attrs=None, renderer=None):
        return mark_safe(value) if value is not None else '-'
👤caio

6👍

You can also use a new widget: I did this so that I could have a widget that created a text display of a date, and a hidden form with the same date in it, so it could be visible to the user, but they cannot change it.

Here is an initial (still testing/to be cleaned up) version:

class DayLabelWidget(forms.Widget):
    def render(self, name, value, attrs):
        final_attrs = self.build_attrs(attrs, name=name)
        if hasattr(self, 'initial'):
            value = self.initial
        if type(value) == type(u''):
            value = datetime.date(*map(int, value.split('-')))
        return mark_safe(
            "%s" % value.strftime("%A (%d %b %Y)")
        ) + mark_safe(
            "<input type='hidden' name='%s' value='%s' />" % (
                name, value
            )
        )

    def _has_changed(self, initial, data):
        return False

You then use this in the field as (widget=DayLabelWidget,).

6👍

Also, don’t forget you can also do {{myform.instance.name}}

3👍

I think this is what you want:
http://code.djangoproject.com/ticket/10427

I patched my django and voila…

👤Trunet

3👍

Here is a take on the approach suggested by @Matthew_Schinkel above, using Django 2.2 and python 3.

from django import forms
from django.utils.safestring import mark_safe

class PlainTextWidgetWithHiddenCopy(forms.Widget):
    def render(self, name, value, attrs=None, renderer=None):
        if hasattr(self, 'initial'):
            value = self.initial

        return mark_safe(
            (str(value) if value is not None else '-') +
            f"<input type='hidden' name='{name}' value='{value}'>"
        )

This is a custom widget that renders the contents of a field as plaintext followed by an html tag that creates a hidden field with the same name and value as the original field.

This means that as well as the value being displayed to the user, it is held by the browser and sent onwards to the view that processes the submitted form.

This is particularly handy if the form POSTs to itself, as the plaintext data would otherwise disappear because the field’s initial value hadn’t been set.

For example if your form contains:

my_field = forms.IntegerField(
    widget=PlainTextWidgetWithHiddenCopy,
    initial=12345)

then this field will render as the following html:

12345<input type='hidden' name='my_field' value='12345'>

When the form is submitted the POST data received by the corresponding view will include:

{'my_field': '12345'}

This means that if the view now re-renders the form then the value of my_field is again set to 12345 just as if the request had been a GET.

As Matthew correctly points out in his subsequent comment, this approach provides no significant protection against a user changing the data that’s sent back in the hidden field. “All user input is evil”.

2👍

Why not use {{ field.data }} ?

👤alj

Leave a comment