Django:扩展用户模型 - UserProfile中的内联用户字段

时间:2012-10-11 15:45:47

标签: python django django-forms

有没有办法在添加/编辑UserProfile模型的表单下显示用户字段?我正在扩展默认的Django用户模型:

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    about = models.TextField(blank=True)

我知道可以制作一个:

class UserProfileInlineAdmin(admin.TabularInline):

然后在User ModelAdmin中内联这个,但是我希望实现相反的效果,比如反向内联,在定义关系的模型页面中显示由OneToOne Relationship(User)指向的模型的字段(UserProfile) 。我不在乎它是在管理员中还是在自定义视图/模板中。我只需要知道如何实现这一目标。

我一直在努力使用ModelForms和Formsets,我知道答案就在那里,但我在Django的经验并不允许我提出解决方案。一个小例子真有帮助!

1 个答案:

答案 0 :(得分:2)

之前提到过。

这是一篇博客文章,我认为这是我最喜欢的解决方案。要点是使用两个ModelForms,并使用<form> kwarg将它们渲染到模板中的单个prefix标记中:

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

这是我喜欢的另一种方法,但也有效。他们在页面上使用两个单独的<form>,具有不同的操作和两个提交按钮:

Proper way to handle multiple forms on one page in Django

这个更具体地谈论用户和用户档案:

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

<强>更新

这是我最终的结果

# 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'),
...