Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango cascade save?
    text
    copied!<p>I have a method on my user registration form that looks like this:</p> <pre><code>def save(self): user = User( username = self.cleaned_data['username'], email = self.cleaned_data['email1'], first_name = self.cleaned_data['first_name'], last_name = self.cleaned_data['last_name'], ) user.set_password(self.cleaned_data['password1']) user.profile = Profile( primary_phone = self.cleaned_data['phone'], ) user.profile.address = Address( country = self.cleaned_data['country'], province = self.cleaned_data['province'], city = self.cleaned_data['city'], postal_code = self.cleaned_data['postal_code'], street1 = self.cleaned_data['street1'], street2 = self.cleaned_data['street2'], street3 = self.cleaned_data['street3'], ) user.save() return user </code></pre> <p>Problem is when I call <code>form.save()</code> it creates the <code>user</code> object as expected, but doesn't save his profile or address. Why doesn't it cascade and save all the sub-models? I suspect I could call <code>user.profile.save()</code> and <code>user.profile.address.save()</code> manually, but I want the whole thing to succeed or fail together. What's the best way to do this?</p> <hr> <p>Current solution:</p> <pre><code>def save(self): address = Address( country = self.cleaned_data['country'], province = self.cleaned_data['province'], city = self.cleaned_data['city'], postal_code = self.cleaned_data['postal_code'], street1 = self.cleaned_data['street1'], street2 = self.cleaned_data['street2'], street3 = self.cleaned_data['street3'], ) address.save() user = User( username = self.cleaned_data['username'], email = self.cleaned_data['email1'], first_name = self.cleaned_data['first_name'], last_name = self.cleaned_data['last_name'], ) user.set_password(self.cleaned_data['password1']) user.save() profile = Profile( primary_phone = self.cleaned_data['phone'], ) profile.address = address profile.user = user profile.save() </code></pre> <p>I had to make <code>profile</code> the "central" object. Needed to set <code>profile.user = user</code> rather than <code>user.profile = profile</code> to make it work (I guess because the key is on the profile model, not on the user model).</p> <hr> <p>Newer solution:</p> <p>I took a hint from <a href="http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/" rel="nofollow noreferrer">this article</a> suggested in <a href="https://stackoverflow.com/questions/569468/django-multiple-models-in-one-template-using-forms/985901#985901">this answer</a>.</p> <p>Now I have separated my model forms and moved the logic into the view:</p> <pre><code>def register(request): if request.POST: account_type_form = forms.AccountTypeForm(request.POST) user_form = forms.UserForm(request.POST) profile_form = forms.ProfileForm(request.POST) address_form = forms.AddressForm(request.POST) if user_form.is_valid() and profile_form.is_valid() and address_form.is_valid(): user = user_form.save() address = address_form.save() profile = profile_form.save(commit=False) profile.user = user profile.address = address profile.save() return HttpResponseRedirect('/thanks/') else: account_type_form = forms.AccountTypeForm() user_form = forms.UserForm() profile_form = forms.ProfileForm() address_form = forms.AddressForm() return render_to_response( 'register.html', {'account_type_form': account_type_form, 'user_form': user_form, 'address_form': address_form, 'profile_form': profile_form}, context_instance=RequestContext(request) ) </code></pre> <p>I'm not too fond of shifting the burden to the view, but I guess I get a bit more flexibility this way?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload