[Answered ]-Django: Extending User Model – Inline User fields in UserProfile

2👍

This has been brought up before.

Here’s a blog post with what I think is my favorite solution. The gist is to use two ModelForms, and render them into a single <form> tag in the template making use of the prefix kwarg:

http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/

Here’s another method which I like a bit less, but is also valid. They use two separate <form>s on the page, with different actions and two submit buttons:

Proper way to handle multiple forms on one page in Django

This one talks more specifically about Users and UserProfiles:

How to create a UserProfile form in Django with first_name, last_name modifications?

Update

Here is what I ended up with

# models.py
class UserProfile(models.Model):

    favorite_color = models.CharField(max_length=30)
    user = models.OneToOneField(User)


# forms.py
class UserProfileForm(forms.ModelForm):

    class Meta:
        model = UserProfile
        # we fill the 'user' value in UserCreateView.form_valid
        exclude = ('user',)


# views.py
from django.contrib.auth.forms import UserCreationForm
class UserCreateView(FormView):

    # url to redirect to after successful form submission
    success_url = reverse_lazy('user_list')
    template_name = "userform.html"

    def get_context_data(self, *args, **kwargs):
        data = super(UserCreateView, self).get_context_data(*args, **kwargs)
        data['userform'] = self.get_form(UserCreationForm, 'user')
        data['userprofileform'] = self.get_form(UserProfileForm, 'userprofile')
        return data

    def post(self, request, *args, **kwargs):
        forms = dict((
            ('userform', self.get_form(UserCreationForm, 'user')),
            ('userprofileform', self.get_form(UserProfileForm, 'userprofile')),
        ))
        if all([f.is_valid() for f in forms.values()]):
            return self.form_valid(forms)
        else:
            return self.form_invalid(forms)

    def get_form(self, form_class, prefix):
        return form_class(**self.get_form_kwargs(prefix))

    def get_form_kwargs(self, prefix):
        kwargs = super(UserCreateView, self).get_form_kwargs()
        kwargs.update({'prefix': prefix})
        return kwargs

    def form_valid(self, forms):
        user = forms['userform'].save()
        userprofile = forms['userprofileform'].save(commit=False)
        userprofile.user_id = user.id
        userprofile.save()
        return HttpResponseRedirect(self.get_success_url())

    def get(self, request, *args, **kwargs):
        return self.render_to_response(self.get_context_data())


# userform.html
<form action="" method="POST" class="form">
    {% csrf_token %}
    {{ userform.as_p }}
    {{ userprofileform.as_p }}
    <button type="submit">Submit</button>
</form>

# urls.py
...
url(r'^create/$', UserCreateView.as_view(), name='user_create'),
...

Leave a comment