Render ForeignKey field as a text field in form but keep foreign key behaviour

Viewed 1325

This question looks stupid ans simple, but I really can't figure it out. I have a model with a foreign key field to another model, lets say:

class Parent:
  name = models.CharField()

class Child:
  name = models.CharField()
  e_id = models.IntegerField()
  parent = models.ForeignKey(Parent)

I render Child instances with defalt django forms, with no any additions. I use inlineformset_factory(Parent, Child, extra=1) if it is important.

And the key moment: django renders parent(which is a foreign key) as a dropdown input. And I need to show parent's id in form as a simple text input and not a dropdown. But I want to keep all behaviour of foreign key and make django validate that a content of parent_id input is a valid and existing id of Patent model.

I tried to create a ChildForm like this:

class ChildForm(django.forms.ModelForm):
    class Meta:
        model = Child
        fields = ('name', 'e_id', 'parent')

    parent = CharField(label=_("Parent"), required=True)

And use it like this:

inlineformset_factory(Parent, Child, extra=1)

And it rendered as a charfield like I want. But here is no validation and smart trasformations of id into instance anymore. If I write incorrect parent_id, I get "Cannot assign "u'21'": "Children.parent" must be a "Parent" instance." error.

So I feel that I'm doing something wrong. I found this answer (Django form ForeignKey database field not as dropdown), but it looks like some kind of monkeypatching and I'm not sure that this is a django-way to do this.

So what is the right way? I use django 1.6.

1 Answers

The thing you need to change here is the widget, not the field. Widgets are the thing that is responsible for outputting the inputs to HTML, whereas fields are responsible for validation. So you just need:

class ChildForm(django.forms.ModelForm):
    class Meta:
        model = Child
        fields = ('name', 'e_id', 'parent')
        widgets = {'parent': forms.TextInput}
Related