如何创建自己的扩展用户表单?

时间:2011-03-31 10:05:33

标签: django forms

我有扩展用户的django模型:

class Student(models.Model):
   user = models.OneToOneField(User, unique=True)
   #other field in that profile
   #other field in that profile
   #other field in that profile

在settings.py中添加了:

AUTH_PROFILE_MODULE = 'myapp.Student'

现在我希望在我的网站上有一些表单来创建该学生用户。最简单的方法是什么? 我不知道我应该在forms.py中创建ModelForm,forms.Form还是其他东西。 此外,我不知道如何在views.py文件中验证此表单。我只想添加这个学生额外字段的新用户。 我还在尝试一些方法,但没有任何作用! 请帮忙!

我正在使用Django1.2.5

2 个答案:

答案 0 :(得分:5)

您是否允许您的用户通过管理站点访问此表单?

如果是这样,那么组合2个表单(用户和学生)的最简单的解决方案是使用管理站点中的内联模型。

解决方案1 ​​(最简单 - 使用管理站点,as document here):

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

from testapp.myauth.models import Student
from testapp.myauth.forms import UserForm

class StudentInline(admin.StackedInline):
    model = Student

class MyUserAdmin(UserAdmin):
    inlines = [
        StudentInline,
    ]

admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)

现在,如果你不喜欢这个解决方案,因为它看起来不漂亮,或者你没有使用管理网站,你可以用艰难的方式去做,并无缝地组合2个表格(你不会看到这是两种不同的形式)。此方法源自此great snippet

解决方案2 (更高级的方法 - 无缝表单组合):

<强> models.py

class Student(models.Model):
    user = models.OneToOneField(User, unique=True)
    address = models.CharField(max_length=10)

# Create student instance on access - very useful if you plan to always have a Student obj associated with a User object anyway
User.student = property(lambda u: Student.objects.get_or_create(user=u)[0])

<强> forms.py

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserChangeForm

from testapp.myauth.models import Student

class StudentForm(forms.ModelForm):
    class Meta:
        model = Student

class UserForm(UserChangeForm):
    class Meta:
        model = User

    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        student_kwargs = kwargs.copy()
        if kwargs.has_key('instance'):
            self.student = kwargs['instance'].student
            student_kwargs['instance'] = self.student
        self.student_form = StudentForm(*args, **student_kwargs)
        self.fields.update(self.student_form.fields)
        self.initial.update(self.student_form.initial)

        # define fields order if needed
        self.fields.keyOrder = (
            'last_name',
            'first_name',
            # etc
            'address',
        )


    def clean(self):
        cleaned_data = super(UserForm, self).clean()
        self.errors.update(self.student_form.errors)
        return cleaned_data

    def save(self, commit=True):
        self.student_form.save(commit)
        return super(UserForm, self).save(commit)

所以我在这里做的是在UserForm中创建StudentForm实例,并相应地组合它们的字段。

我唯一的建议是考虑将您的个人资料模型重命名为更通用的而不是学生(例如UserProfile会起作用),因为您永远不知道将来您可能最终会有不同类型的用户,其他学生(例如教师)。

答案 1 :(得分:0)

您很可能想要创建两个ModelForms。 您可以在一个视图中处理它们。只需先保存User对象, 然后将该用户添加到您在POST上通过模型创建的Student对象。

有关详情,请查看该页面上的this post,具体问题7。