tags:

views:

170

answers:

5

In Django, how do I associate a Form with a Model so that data entered into the form are inserted into the database table associated with the Model? How do I save that user input to that database table?

For example:

class PhoneNumber(models.Model):
    FirstName = models.CharField(max_length=30)
    LastName = models.CharField(max_length=30)
    PhoneNumber = models.CharField(max_length=20)

class PhoneNumber(forms.Form):
    FirstName = forms.CharField(max_length=30)
    LastName = forms.CharField(max_length=30)
    PhoneNumber = forms.CharField(max_length=20)

I know there is a class for creating a form from the the model, but even there I'm unclear on how the data actually gets to the database. And I'd like to understand the inner workings before I move on to the time-savers. If there is a simple example of how this works in the docs, I've missed it.

Thanks.

UPDATED: To be clear -- I do know about the ModelForm tool, I'm trying to figure out how to do this without that -- in part so I can better understand what it's doing in the first place.

ANSWERED:

With the help of the anwers, I arrived at this solution:

Form definition:

class ThisForm(forms.Form)
    [various Field assignments]

    model = ThisModel()

Code in views to save entered data to database:

if request_method == 'POST':
    form = ThisForm(request.POST)
    if form.is_valid():
        for key, value in form.cleaned_data.items():
            setattr(form.model, key, value)
        form.model.save(form.model)

After this the data entered in the browser form was in the database table.

Note that the call of the model's save() method required passage of the model itself as an argument. I have no idea why.

CAVEAT: I'm a newbie. This succeeded in getting data from a browser to a database table, but God only knows what I've neglected or missed or outright broken along the way. ModelForm definitely seems like a much cleaner solution.

+2  A: 

I'm not sure which class do you mean. I know that there were a helper, something like form_for_model (don't really remember the exact name; that was way before 1.0 version was released). Right now I'd it that way:

import myproject.myapp.models as models

class PhoneNumberForm(forms.ModelForm):
    class Meta:
        model = models.PhoneNumber

To see the metaclass magic behind, you'd have to look into the code as there is a lot to explain :]. The constructor of the form can take instance argument. Passing it will make the form operate on an existing record rather than creating a new one. More info here.

gavoja
I can display the Form to a browser screen for a user to enter data. How do I get that data to the proper database table?
chernevik
Thanks, this helped me realize I should assign to a model attribute explicitly.
chernevik
+1  A: 

I think ModelForm.save documentation should explain it. With its base class (Form) you would need to use the Form.cleaned_data() to get the field values and set them to appropriate Model fields "by hand". ModelForm does all that for you.

vmj
A: 

The Django documentation is pretty clear on this subject. However, here is a rough guide for you to get started: You can either override the form's save method or implement that functionality in the view.

if form.is_valid() # validation - first the fields, then the form itself is validated
    form.save()

inside the form:

def save(self, *args, **kwargs):
    foo = Foo()
    foo.somefield = self.cleaned_data['somefield']
    foo.otherfield = self.cleaned_data['otherfield']
    ...
    return foo.save()
shanyu
Friend, if the documentation is clear, I've missed it. And I've been over that documentation a time or two.
chernevik
+3  A: 

Back when I first used Forms and Models (without using ModelForm), what I remember doing was checking if the form was valid, which would set your cleaned data, manually moving the data from the form to the model (or whatever other processing you want to do), and then saving the model. As you can tell, this was extremely tedious when your form exactly (or even closely) matches your model. By using the ModelForm (since you said you weren't quite sure how it worked), when you save the ModelForm, it instantiates an object with the form data according to the model spec and then saves that model for you. So all-in-all, the flow of data goes from the HTML form, to the Django Form, to the Django Model, to the DB.

Some actual code for your questions:

To get the browser form data into the form object:

if request.method == 'POST':
    form = SomeForm(request.POST)
    if form.is_valid():
        model.attr = form.cleaned_data['attr']
        model.attr2 = form.cleaned_data['attr2']
        model.save()
else:
    form = SomeForm()
return render_to_response('page.html', {'form': form, })

In the template page you can do things like this with the form:

<form method="POST">
{{ form.as_p }}
<input type="submit"/>
</form>

That's just one example that I pulled from here.

Adam
So you assign a model to an attribute of the form, perhaps through Meta as gavoja suggests, and use that model's save() method. I suppose the data move can be automated by looping through cleaned_data.keys() and using setattr(model, key, cleaned_data[key]). I think this will do what I need -- I'll try it.
chernevik
+1  A: 

Just curious, why are you trying to do this without the ModelForm?

jobscry
I'd like to know the guts of how this works. First on general principles, and second because I think it would help me find the best integration of a pre-Django database interface layer I've written with Django.
chernevik