Django models with OneToOne relationships?

Let's say I use the standard auth.models.User plus my user models Profile and Address , which look like this:

 class Profile(models.Model): user = models.OneToOneField(User) primary_phone = models.CharField(max_length=20) address = models.ForeignKey("Address") class Address(models.Model): country = CountryField(default='CA') province = CAProvinceField(default='BC') city = models.CharField(max_length=80) postal_code = models.CharField(max_length=6) street1 = models.CharField(max_length=80) street2 = models.CharField(max_length=80, blank=True, null=True) street3 = models.CharField(max_length=80, blank=True, null=True) 

Now I want to create a registration form. I could create a ModelForm based ModelForm , but that would not include the fields for Profile and Address (which are needed). So what is the best way to build this form? Should I use ModelForm at all?

Also, how would I use the same form to edit a complex object? I could easily pass the profile instance back to it, which contains links to the necessary Address and Profile objects, but how do I get it to populate the fields for me?

+7
django django-forms
source share
3 answers

How about using 3 separate ModelForm . One for Address , one for User and one for Profile , but with:

 class ProfileForm(ModelForm): class Meta: model = Profile exclude = ('user', 'address',) 

Then process these 3 forms separately in your views. In particular, for ProfileForm use save with commit=False to update the User and Address fields in the instance:

 # ... profile_form = ProfileForm(request.POST) if profile_form.is_valid(): profile = profile_form.save(commit=False) # `user` and `address` have been created previously # by saving the other forms profile.user = user profile.address = address 

Feel free to use transactions here to make sure the rows are inserted only if 3 forms are valid.

+8
source share

You should study the officially recommended way to expand the User model first, as can be seen from the documentation , which, in my opinion, comes directly from the project manager’s personal blog about the subject . (The actual blog article is quite old, now)

As for your actual problem with forms, look at the project manager, who can reuse the django-profiles application, and see if your code fixes your problem. In particular, these functions and the types in which they are used.

Edited to add:

I looked into it a little (since I needed to do it myself). Something like this seems to be enough:

 # apps.profiles.models from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) ... birth_date = models.DateField(blank=True, null=True) joined = models.DateTimeField(auto_now_add=True) modified = models.DateTimeField(auto_now=True) class Meta: verbose_name = 'user profile' verbose_name_plural = 'user profiles' db_table = 'user_profiles' class Address(models.Model): user = models.ForeignKey(UserProfile) ... # apps.profiles.forms from django import forms from django.forms import ModelForm from django.forms.models import inlineformset_factory from django.contrib.auth.models import User from apps.profiles.models import UserProfile, Address class UserForm(ModelForm): class Meta: model = User ... class UserProfileForm(ModelForm): class Meta: model = UserProfile ... AddressFormSet = inlineformset_factory(UserProfile, Address) 

I used "..." to edit the content in the code above. I have not tested this yet, but, looking at the examples and documentation on the forms, I believe that this is correct.

Note. I put the FK from the Address model in UserProfile, and not vice versa, as in your question. I believe inline forms require this to work correctly.

Then, of course, in your views and templates you will process UserForm, UserProfileForm, and AddressFormSet separately, but they can all be inserted into the same form.

+3
source share

I think you are looking for built-in formats with sample models. This will help you deal with several forms on one page, as well as take care of foreign keys.

Update:

Perhaps this question will also help you: Django: multiple models in one template using forms

+1
source share

All Articles