1

I'm trying to make a CreateView have a readonly field with a set value, but I'm unable to make that work.

I have a model with a ForeignKey to another model:

class CompanyNote(TimeStampedModel):
    company = models.ForeignKey(Company)
    note = models.TextField(blank=True)

And I have a CreateView:

class CompanyNoteCreateView(CreateView):
    model = models.CompanyNote
    form_class = CompanyNoteForm

That uses a custom ModelForm:

class CompanyNoteForm(forms.ModelForm):

    company = forms.ChoiceField(
        widget=forms.widgets.Select(attrs={'readonly': 'readonly'}))

    class Meta:
        model = models.CompanyNote

As you see, the widget for the field in question is readonly. This is because I pick up the company as a part of the URL, as in company/1/note/add . I have no trouble picking up the "1" and finding the right company object, but I don't know how to set the readonly field.

I tried:

def get_initial(self):
    initial = super(CompanyNoteCreateView, self).get_initial()
    initial['company'] = self.get_company().id
    return initial

But that didn't work. The Widget is empty, which may be the problem. Perhaps I'm barking up the wrong tree here. Any ideas welcome.

Nathaniel
  • 666
  • 4
  • 15
Lennart Regebro
  • 167,292
  • 41
  • 224
  • 251

3 Answers3

1

Use a ModelChoiceField

class CompanyNoteForm(forms.ModelForm):
    company = forms.ModelChoiceField(queryset=models.Company.objects.all(), widget=forms.widgets.Select(attrs={'readonly': 'readonly'}))
Nathaniel
  • 666
  • 4
  • 15
  • That works, in as much that I can now set the initial value. Funnily enough, it's not read_only though (neither in Firefox nor in Chrome). It *looks* readonly, and Firefox even shows a little "Not allowed" mouse pointer. But it's not readonly... – Lennart Regebro Jan 25 '13 at 18:48
  • It might remove it altogether, but what if you add to `class Meta:` an exclude of `exclude = ('company',)` I'm not able to try this right now so it might remove the company altogether. – Nathaniel Jan 25 '13 at 18:56
  • Weirdly enough that just moves the field to the bottom of the form. I think it gets added back since it's required. I'll probably override the SelectWidget to handle readonly more sensibly. – Lennart Regebro Jan 25 '13 at 19:01
1

Have you tried setting the attribute in the Form's Meta class?

I experienced an issue where Form attributes were not applied for Model Fields if set in the base class definition, but they worked correctly in the Meta class:

class CompanyNoteForm(forms.ModelForm):
    class Meta:
        model = models.CompanyNote
        widgets = {'company': forms.widgets.Select(attrs={'readonly': True,
                                                          'disabled': True})}

Otherwise check this answer out.

Worst case scenario, make company a hidden field?

Community
  • 1
  • 1
Lysergia25
  • 134
  • 2
  • 6
  • It also solves the initial value problem, and it's slightly "cleaner" than setting the form field, so this is a good solution. The widget is still not actually read only, so I still need a ReadOnlySelectWidget, and also to make the field read-only as per other questions and answers. – Lennart Regebro Jan 26 '13 at 11:49
  • For a `Select` you need to set also the `disabled` attribute as specified in [this answer](http://stackoverflow.com/a/4945913/1935366) – gipi Oct 29 '14 at 18:24
0

I could not find this answer anywhere, that I could actually get to work. But I found a different approach. Set the field to be hidden with forms.HiddenInput() widget. Then the value you pass in from the view will be assigned but the user cannot access it.

widgets = {'field_name': forms.HiddenInput()}

I'm using ModelForm class so my syntax might be different from yours.