Django Admin中带有一对一字段的内联
在我的模型中,你可以看到我有一个叫做SpecializedProfile的部分,它和UserProfile之间是一对一的关系,而UserProfile又和django的用户模型之间也是一对一的关系。
我想为SpecializedProfile创建一个管理界面,这个界面里包含UserProfile和django用户模型的内联,这样我就可以一次性创建一个SpecializedProfile,而不需要分别去UserProfile页面和用户页面。
这是我的模型:
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希望内联出现在定义了一对一字段的模型上,而不接受反向关系。我不想为了让它工作而重新调整我的模型结构……有没有什么办法可以让内联在我的模型上正常工作呢?
2 个回答
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
我通过把反向关系设置为内联来解决那个错误,不是从个人资料(Profile)到用户(User),而是从重写的用户(User)到个人资料(Profile):
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),去掉了添加操作,并把一些字段链接改成了自定义的。