48

I want to fill up form with data from model instance. But my form has less fields than model. If I have code like this:

class Item(models.Model)
    name = models.CharField(max_length=100)
    price = models.PositiveIntegerField()

class ItemForm(forms.Form):
    name = forms.CharField()

What wrong is with this function and how it should look to be good?

def bound_form(request, id):
    item = Item.objects.get(id=id)
    form = ItemForm(item.name)
    return render_to_response('bounded_form.html', {'form': form})

I getting error like this: AttributeError: 'ItemForm' object has no attribute 'get'

BenMorel
  • 34,448
  • 50
  • 182
  • 322
krzyhub
  • 6,285
  • 11
  • 42
  • 68

2 Answers2

76

Generally when creating a form for a Model, you will want to use ModelForm. It keeps to the DRY principle such that you do not have to redefine field types for the form class. It also automatically handles validation. You retain full flexibility to customize the fields and widgets used. Use fields to specify the fields you want or exclude to specify fields to ignore. With your example:

from django import forms
from django.shortcuts import get_object_or_404

class ItemForm(forms.ModelForm):
    class Meta:
        model = Item
        fields = ("name", )

def bound_form(request, id):
    item = get_object_or_404(Item, id=id)
    form = ItemForm(instance=item)
    return render_to_response('bounded_form.html', {'form': form})

get_object_or_404() is useful here as a form of error handling. Using Item.objects.get(id=id) on a missing ID will throw an uncaught Item.DoesNotExist exception otherwise. You could use a try/except block also of course.

Valter Silva
  • 16,446
  • 52
  • 137
  • 218
JCotton
  • 11,650
  • 5
  • 53
  • 59
  • 2
    This should be marked as the correct answer, because it doesn't depend on any specific field, just uses the modelform – vascop Sep 21 '11 at 21:31
  • 1
    What if you have a field that isn't directly stored on the model but still want to edit it through this form. Using `ModelForm` is fine, but how about creating and initializing an additional field, perhaps with a value from a ForeignKey of the model? – jozxyqk Nov 23 '14 at 08:51
  • ModelForms support ForeignKey and ManyToManyField attributes. https://docs.djangoproject.com/en/1.4/topics/forms/modelforms/#field-types – Sam Kauffman May 08 '15 at 15:11
  • This answer seems more accurate than the selected one. This way I don't have to update the fields manually. Thanks Silva. – Iftieaq Feb 09 '18 at 18:23
  • @jozxyqk you can still pass initial={,,..} to a ModelForm. In that model, you would presumably have defined those "extra" fields (that aren't directly tied to the model. Say if you define in your modelform: foo = Charfield(....), then you canstill do form = ItemForm(instance=item, initial={"foo":"blabla"}) – logicOnAbstractions Oct 20 '21 at 12:52
51
def bound_form(request, id): 
    item = Item.objects.get(id=id) 
    form = ItemForm(initial={'name': item.name}) 
    return render_to_response('bounded_form.html', {'form': form}) 
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Cadilac
  • 1,090
  • 11
  • 17
  • 2
    I hate to be critical but I have no idea how to implement your answer. Does this go in forms.py or views.py? How do I use it? – Austin A Feb 18 '15 at 22:24
  • 1
    @AustinA: Function `bound_form` is a view, so it goes in views.py, and he's passing the `initial` argument to the form to set the initial form values. – Serrano Mar 18 '15 at 13:50