Django Admin使用OneToOne字段进行内联

时间:2014-10-31 21:56:08

标签: python django django-admin

在我的模型中,您可以看到我有一个与UserProfile具有OneToOne关系的SpecializedProfile,与django用户模型具有OneToOne关系。

我想为包含UserProfile和django用户模型的内联的SpecializedProfile创建一个admin,这样我就可以一次创建一个SpecializedProfile,而无需转到UserProfile页面和User页面。

这是我的模特:

class UserProfile(models.Model):
    user_auth = models.OneToOneField(User, related_name="profile", primary_key=True)
    # more fields...


class SpecializedProfile(models.Model):
    profile = models.OneToOneField(UserProfile, related_name="specialized_profile", primary_key=True)
    # More fields...

这是我尝试创建管理员:

class UserInline(admin.TabularInline):
    model = User
    fk_name = 'profile__specialized_profile'

class ProfileInline(admin.TabularInline):
    model = UserProfile
    fk_name = 'specialized_profile'

class SpecializedProfileAdmin(admin.ModelAdmin):
    model = SpecializedProfile
    inlines = [
        UserInline, ProfileInline
    ]

admin.site.register(SpecializedProfile, SpecializedProfileAdmin)

管理员无法正常工作,我收到此错误:

<class 'profiles.admin.ProfileInline'>: (admin.E202) 'profiles.UserProfile' has no field named 'trainer'.
<class 'profiles.admin.UserInline'>: (admin.E202) 'auth.User' has no ForeignKey to 'profiles.SpecializedProfile'.

似乎django希望内联属于定义OneToOne字段的模型,并且不接受反向关系。我宁愿不必重组我的模型来完成这项工作......我能做些什么来使内联按原样使用我的模型?

3 个答案:

答案 0 :(得分:0)

我通过反面内联修复了这个错误,而不是从配置文件到用户,而是从覆盖用户到配置文件:

class ProfileInline(admin.StackedInline):
    model = Profile

class IspUserAdmin(UserAdmin):
    list_display = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'is_superuser', 'is_active')
    list_filter = ('date_joined', 'last_login', 'is_staff', 'is_superuser', 'is_active',)
    inlines = (ProfileInline,)

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

然后我还调整了Profile admin(删除了添加操作并将一些字段链接更改为自定义链接)。

答案 1 :(得分:0)

github上有一个django模块可以为你做这件事,而不必扭转关系:django_reverse_admin

安装完成后,管理员会看起来像:

# admin.py
from django_reverse_admin import ReverseModelAdmin


class SpecializedProfileAdmin(ReverseModelAdmin):
    model = SpecializedProfile
    inline_reverse = ['profile']
    inline_type = 'tabular'  # could also be 'stacked'

admin.site.register(SpecializedProfile, SpecializedProfileAdmin)

不幸的是,我不认为它可以做嵌套内联(Django也不能),所以这只能解决部分问题。我知道你不想改变你的数据库结构,但是SpecializedProfile看起来更像是UserProfile的子类。如果你像这样重写了你的模型:

class SpecializedProfile(UserProfile):
    # More fields...

然后你可以让管理员这样:

# admin.py
from django_reverse_admin import ReverseModelAdmin

class UserProfileAdmin(ReverseModelAdmin):
    model = UserProfile
    inline_reverse = ['user_auth']
    inline_type = 'tabular'


class SpecializedProfileAdmin(ReverseModelAdmin):
    model = SpecializedProfile
    inline_reverse = ['user_auth']
    inline_type = 'tabular'

admin.site.register(SpecializedProfile, SpecializedProfileAdmin) 
admin.site.register(UserProfile, UserProfileAdmin)

这样,您可以查看UserProfile和SpecializedProfile的所有内联。

答案 2 :(得分:-1)

nested inlines (inline inside inline)中无法django.contrib.admin

也许这可以帮到你:

class UserInline(admin.TabularInline):
    model = User

class ProfileInline(admin.TabularInline):
    model = UserProfile
    inlines = [UserInline]

class SpecializedProfileAdmin(admin.ModelAdmin):
    model = SpecializedProfile
    inlines = [ProfileInline]

您还需要提供自己的模板,这些模板将在顶级内联和子内联中进行嵌套迭代。

另请查看this,也许可以帮助您。