views:

37

answers:

2

This is actually a follow-up to a previous question.

A user's profile data is spread over several different models, like so:

# Simplified versions, actual classes contain many more fields.

class Profile(models.Model):  # returned by Django's User.get_profile()
    user = models.OneToOneField(User)  

    home_address = models.OneToOneField(Address)
    work_address = models.OneToOneField(Address)

    language = models.CharField(max_length=20)

class Address(models.Model):
    street = models.CharField(max_length=100)
    city = models.CharField(max_length=100)

... and Django's User, of course.

I want the user to enter all of his profile data in one view, in particular these pieces of information:

  • username (User)
  • email (User)
  • language (Profile)
  • home_address.street (Address)
  • home_address.city (Address)
  • work_address.street (Address)
  • work_address.city (Address)

So, what would be the simplest/Django way to

  1. construct such a form?
  2. output the form in the template?
  3. handle the incoming form data, split it to different models and create the necessary objects (i.e. a User, a Profile and 2 Address objects)?
A: 

Most practical way is, i guess, using modelForm and formsets...

You can use model form to create forms from a model. Docs here.... You can use inline formset to create forms and save data easily... Doc here...

But, of course, related models must have foreignkey to either user or Profile. Your model structure may not be suitable, because as far as i know, inlined model must have a foreignkey to the other, so at this point, your foreignkey to Profile needed to be in Address model... But as i said, i am not sure.you may give it a try...

Since you have proper foreignKey relations, you can use inline formsets with modelform to create a form from many models...

EDIT:

As far as i understand, you can either use modelforms (without formsets) and easily cerate your form in the template. But in your view funtion that will process the posted data, you have to set foreign one to one connections manually. Like:

home = Address.objects.create(...)
work = Address.objects.create(...)
Profile.objects.create(home_address=home, work_address=work,...)

Or you can alter your models:

class Profile(models.Model):  # returned by Django's User.get_profile()
    user = models.OneToOneField(User)  
    language = models.CharField(max_length=20)

class Address(models.Model):
    profile = models.ForeignKey(Profile)
    street = models.CharField(max_length=100)
    city = models.CharField(max_length=100)
FallenAngel
I have looked into formsets and inline formsets, and they appear to be suitable for cases where you have many objects of a kind, or a parent object and several child objects of a kind, respectively. So no, I don't think they help here as the model hierarchy is more complicated.
stalemate
A: 

I think you're at the point where modelforms and formsets will require more work to customise than you will save by using them. So, I would use a standard (non-model) form, define the field types manually, and save them all to the relevant models explicitly - either in the view, or by defining your own save() method on the form and calling that.

Daniel Roseman