使用OneToOneField扩展Django Admin UserCreationForm

时间:2018-02-13 11:43:56

标签: python django python-2.7 django-forms django-admin

我正在尝试扩展django管理员UserCreationForm以包含来自OneToOneField上相关的另一个表的字段。

这是我的相关表格:

class Profile(models.Model):
    user = models.OneToOneField(
        User,
        on_delete=models.CASCADE
    )
    supervisor = models.ForeignKey(
        User,
        related_name='supervisor',
        on_delete=models.DO_NOTHING,
        blank = True,
        null = True
    )

我的管理员表单:

from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from django import forms

class EmailRequiredMixin(object):
    def __init__(self, *args, **kwargs):
        super(EmailRequiredMixin, self).__init__(*args, **kwargs)
        # make user email field required
        self.fields['email'].required = True


class MyUserCreationForm(EmailRequiredMixin, UserCreationForm):
    supervisor = forms.Select()

    class Meta:
        model = User
        fields = ['username',]

    def save(self, commit=True):
        if not commit:
            raise NotImplementedError("Can't create User and UserProfile without database save")
        user = super(MyUserCreationForm, self).save(commit=True)
        profile = Profile(user=user, supervisor=self.cleaned_data['supervisor'])
        profile.save()
        return user, profile

class EmailRequiredUserAdmin(UserAdmin):
    inlines = [ProfileInline, ]
    list_display = ['username', 'email', 'first_name', 'last_name', 'is_staff', 'get_supervisor', 'get_is_supervisor', 'get_is_project_manager']
    form = MyUserChangeForm
    add_form = MyUserCreationForm
    add_fieldsets = ((None, {'fields': ('username', 'email',
                                        'password1', 'password2'), 'classes': ('wide',)}),)

    def get_supervisor(self, instance):
        return instance.profile.supervisor
    get_supervisor.short_description = 'Supervisor'

    def get_is_supervisor(self, instance):
        return instance.profile.is_supervisor()
    get_is_supervisor.short_description = 'Is Supervisor'

    def get_is_project_manager(self, instance):
        return instance.profile.is_project_manager()
    get_is_project_manager.short_description = 'Is Project Manager'

    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(EmailRequiredUserAdmin, self).get_inline_instances(request, obj)

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

在django-admin中,它只显示正常的创建表单,但我需要包含主管。我知道在这个阶段我没有为主管提供查询集,但我认为这解释了我想要实现的目标以及我尝试过的内容。

非常感谢帮助。

1 个答案:

答案 0 :(得分:3)

您还需要将管理员字段添加到管理员add_fieldsets。

class MyTestForm(UserCreationForm):
    supervisor = forms.ModelChoiceField(queryset=User.objects)

    def save(self, commit=True):
        supervisor = self.cleaned_data['supervisor']
        # Save user first 
        user = super(MyTestForm, self).save(commit=True)
        profile = Profile.objects.create(user=user)
        profile.supervisor = supervisor
        profile.save()
        return user


class MyUserAdmin(UserAdmin):
    add_form = MyTestForm
    form = UserChangeForm
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('supervisor', 'username', 'password1', 'password2')
        }),
    )

我测试了这个解决方案,主管在创建步骤中显示为下拉列表。 希望它有所帮助。