我正在创建一个多租户应用程序,并拥有以下抽象类,所有相关的租户特定模型都继承自:
class TenantAwareModel(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
class Meta:
abstract = True
当在Django管理中注册模型时,我想保持我的代码DRY,而不必添加'tenant'到每个search_fields, list_display, list_filter等,所以我尝试创建一个超类来继承。
class TenantAwareAdmin(admin.ModelAdmin):
class Meta:
abstract = True
# change_form_template = "admin/professional_enquiry_change_form.html"
search_fields = ('tenant__id', 'tenant__name', 'tenant__domain',)
list_display = ('tenant',)
list_filter = ('tenant',)
然后尝试在其他模型的注册中继承它。例如
class UserAdmin(TenantAwareAdmin, admin.ModelAdmin ):
...
这种方法与tenanttawaremodel的工作方式相匹配。
class TenantAwareModel(models.Model):
tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
class Meta:
abstract = True
class User(AbstractUser, Uuidable, Timestampable, TenantAwareModel):
...
它当然给了我:
django.core.exceptions.ImproperlyConfigured: The model TenantAwareModel is abstract, so it cannot be registered with admin.
有谁知道避免重复代码的正确方法吗?
Meta
类和abstract=True
类只能在模型定义中定义,不能在ModelAdmin
中定义。
TenantAwareModel
是一个抽象模型,它允许您避免在其他模型的定义中重复公共字段,但是您不能在管理站点中注册抽象模型。抽象模型与任何表都没有关系,它的唯一任务是作为一个基,从这个基中继承其他表示表的模型(不是抽象模型),并且可以在管理站点中注册。
为了避免在search_fields, list_display等中重复相同的字段,您应该创建这样的mixin:
class TenantAwareAdminMixin:
search_fields = [..., ...]
list_display = [..., ...]
...
和继承
class UserAdmin(TenantAwareAdminMixin, admin.ModelAdmin):
...
但是有一个问题…如果你覆盖了TenantAwareAdminMixin
中定义的一些字段,这将覆盖mixin提供的值,迫使你显式地将继承的值加上那些新值,就像这样:
class UserAdmin(TenantAwareAdminMixin, admin.ModelAdmin):
list_display = TenantAwareAdminMixin.list_display + ['new_value']
...
可以通过重写get_list_display等方法来获得类似的结果。