0

I have a model with some fields. Consider the model below.

class Item(models.Model):
    a = models.CharField(max_length=200)
    b = models.BooleanField(default=False)
    c = models.CharField(max_length=200)

A form class for the corresponding model.

class ItemForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    class Meta:
        model = Item
        localized_fields = '__all__'
        fields = [
            'a',
            'b',
            'c',
        ]

And a view for the form. The view class uses a template which shows all the fields. But the field c will be shown only if field b is true.

{% if form.b.value %}
    {% form.c %}
{% endif %}

field c is not editable and I just want to show the value which is already pre-defined.

The issue is that if I use a if condition in the template, (Assume b is false) when I load the form it shows 2 fields a and b and when I submit the form with b set to true, the form reloads without saving showing all three fields with the value of field c as blank.

field c already has a value and it is present in the DB but it doesn't show up. Why is that?

EDIT: Here is my view, pretty simple

class ItemGeneral(UpdateView):
    form_class = ItemUpdateForm
    template_name = 'pretixcontrol/item/index.html'
    permission = 'can_change_items'

    @transaction.atomic()
    def form_valid(self, form):
        # some code
        return super().form_valid(form)
JRodDynamite
  • 12,325
  • 5
  • 43
  • 63

1 Answers1

1

To make c un-editable, I would use the Field.disabled attribute new in Django 1.9. See this post for information on how to use it and what to do if you're in 1.8 or older:

In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited?

As far as the saving issue goes, I would have to see your view to be sure but it sounds like something may be going awry during form validation. Your form will expect all three fields since that's how it's initialized, but your template can remove a field independent of the view logic. Perhaps the issue crops up when only two of the three expected fields go through form.is_valid()?

Would it be acceptable for c to always be exposed in the page source? You could render the form normally in all cases, then check the value of field b using jQuery/JS and conditionally .hide it.

Alternatively, you could check your model's attributes in the view and conditionally remove a field from the form's self.fields dict or override the init method.

Community
  • 1
  • 1
souldeux
  • 3,615
  • 3
  • 23
  • 35
  • This seems like a good approach, using JS would be a good way to listen to changes on the field `b` and then toggle both field `c` according to the value of field `b`. You can add attributes to fields using [form.widgets](https://docs.djangoproject.com/en/1.10/ref/forms/widgets/#widget) and setting attribute to readonly. – kt14 Aug 09 '16 at 18:28
  • `Field.disabled` did the trick. I'm not sure how I missed it. Thanks! :) – JRodDynamite Aug 18 '16 at 05:16