Allez-vous permettre à votre utilisateur d'accéder à ce formulaire via le site d'administration? Si oui, la solution la plus simple pour combiner les deux formulaires (Utilisateur et Étudiant) serait d'utiliser le modèle Inline dans le site Admin.
Solution 1 (plus simple - utiliser le site Admin, 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)
Maintenant, si vous ne aimez pas cette solution car il ne semble pas assez, ou vous ne pas utiliser l'administrateur site, vous pouvez le faire à la dure et combiner les 2 formulaires de façon transparente (vous ne verrez pas que c'est 2 formes différentes). Cette méthode a été dérivée de cette great snippet.
Solution 2 (la méthode plus avancée - combinaison de forme transparente):
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)
Alors ce que je fait ici était de créer une instance de StudentForm dans le UserForm et combinez leurs champs en conséquence. Je vous suggère seulement de renommer votre modèle de profil en quelque chose de plus générique au lieu de Student (par exemple, UserProfile fonctionnerait) car on ne sait jamais si dans le futur vous pourriez avoir différents types d'utilisateurs, d'autres étudiants (par exemple un enseignant).