简体   繁体   English

Django-将UserAdmin子类化以创建动态模板?

[英]Django - subclassing UserAdmin to create dynamic templates?

I'm not quite sure how to phrase the question that I want to ask. 我不太确定如何用语表达我想问的问题。 Let's say that you have two profile objects that could possibly be associated with a User. 假设您有两个配置文件对象,它们可能与一个用户相关联。 Only one of them will be associate (there's a one to one mapping) but it could be one of two possible profile objects. 其中只有一个是关联的(存在一对一的映射),但是它可能是两个可能的配置文件对象之一。 My admin code looks like this: 我的管理代码如下所示:

admin.site.unregister(User)

class AProfileInline(admin.StackedInline):
    model = UserProfileA

class BProfileInline(admin.StackedInline):
    model = UserProfileB

class UserProfileAdmin(UserAdmin):
    inlines = [AProfileInline, BProfileInline, ]

admin.site.register(User, UserProfileAdmin)

This works ok, but of course it displays unnecessary information. 可以,但是当然会显示不必要的信息。 It would be nice if the admin page would only display the proper inline. 如果管理页面仅显示正确的内联代码,那就太好了。 I imagine this is complicated and probably is a problem if, for example, I want to change from one profile type to another. 我想这很复杂,例如,如果我想从一种配置文件类型更改为另一种配置文件类型,可能是一个问题。 Any thoughts? 有什么想法吗?

This is one way to do it. 这是做到这一点的一种方法。 Keep in mind, this is a hack . 请记住, 这是一个hack I based this code off of the ModelAdmin code in django.contrib.admin.options . 我将此代码基于django.contrib.admin.options中的ModelAdmin代码。

admin.site.unregister(User)

class AProfileInline(admin.StackedInline):
    model = UserProfileA

class BProfileInline(admin.StackedInline):
    model = UserProfileB

class UserProfileAdmin(UserAdmin):
    inlines = [AProfileInline, BProfileInline, ]

    def get_object(self, *args, **kwargs):
        obj = super(UserProfileAdmin, self).get_object(*args, **kwargs)
        if obj:
            self.inline_instances = []
            if AProfileInline.model.objects.filter(user=obj):
                inline_instance = AProfileInline(self.model, self.admin_site)
                self.inline_instances.append(inline_instance) 
            if BProfileInline.model.objects.filter(user=obj):
                inline_instance = BProfileInline(self.model, self.admin_site)
                self.inline_instances.append(inline_instance)
        return obj

admin.site.register(User, UserProfileAdmin)

This solution assumes that both UserProfileA and UserProfileB have foreign key relations to User through a field called user . 此解决方案假定UserProfileAUserProfileB都通过名为user的字段与User具有外键关系。

The change_view and delete_view functions call get_object , so this code should properly replace the inline form instances before these views are rendered. change_viewdelete_view函数调用get_object ,因此此代码应在呈现这些视图之前正确替换内联表单实例。

This code overrides get_object to perform the following extra actions: 此代码覆盖get_object以执行以下额外操作:

  1. The inline forms are empty by default (for pre-existing objects) 内联表单默认为空(对于预先存在的对象)
  2. If a UserProfileA is found that references the current User (through the user field), an inline form for UserProfileA is added. 如果UserProfileA发现引用当前User (通过user字段),用于内联形式UserProfileA加入。
  3. If a UserProfileB is found that references the current User (through the user field), an inline form for UserProfileB is added. 如果UserProfileB发现引用当前User (通过user字段),用于内联形式UserProfileB加入。

Quirks of this solution: 此解决方案的怪癖:

  • UserProfileAdmin.__init__ will still create a default version of self.inline_instances which will then be overwritten whenever change_view or delete_view are used. UserProfileAdmin.__init__仍然会创建一个默认版本self.inline_instances每当其将被覆盖change_viewdelete_view使用。
  • This function was never meant to do what the above code is using it for. 此函数从不打算执行上面的代码将其用于的目的。 If UserProfileAdmin.get_object is called in any other code, the inline forms will be needlessly recalculated. 如果以任何其他代码调用UserProfileAdmin.get_object ,则将不必要地重新计算内联表单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM