首页 > 解决方案 > 如何将依赖项从一个应用程序注入到另一个应用程序的 Django 类中?

问题描述

是否有一种干净的方法可以将依赖项从一个 Django 应用程序注入另一个应用程序?

我有多个 Django 应用程序,其中一个是基础应用程序。这意味着,其他应用程序依赖于它,但基础应用程序不应该知道其他应用程序。在大多数情况下,对于使用 ForeignKeys 和 ManyToMany 关系到基本应用程序模型的依赖项来说,这不是问题。但是,在构建管理类时,为了向相应的依赖类添加内联和链接,有必要在基础应用程序中指定这一点。是否可以直接从依赖的应用程序注入它?

标签: django

解决方案


除了添加 inlines的答案之外,我还必须为列表显示和列表过滤器的类添加属性。下面是为一个 ForeignKey 链接模型添加此代码的代码。Foo 是一个父模型(在组合优于继承的意义上),其他几个子模型通过 OneToOne 或其他应用程序的 ForeignKey 字段链接到该模型。这确保了父模型以及它所在的应用程序对其子模型没有任何依赖关系。

在父 App A 中定义的模型和管理类。

# app_a/models.py
from django.db import models

class Foo(models.Model):
    name = models.CharField(max_length=64)
# app_a/admin.py
from django.contrib import admin
from .models import Foo

@admin.register(Foo)
class FooAdmin(admin.ModelAdmin):
    list_display = ["name"]
    list_display_links = ("name",)
    list_filter = []
    list_select_related = []

子 App B 中定义的模型和管理类。

# app_b/models.py
from django.db import models
from app_a.models import Foo

class BarComponent(models.Model):
    foo = models.OneToOneField(
        Foo,
        primary_key=True,
        related_name="bar_component",
        on_delete=models.CASCADE,
    )
    bar_type = models.CharField(max_length=42)
# app_b/admin.py
from django.contrib import admin
from django.core.exceptions import ObjectDoesNotExist

from .models import BarComponent
from app_a.admin import FooAdmin

@admin.register(BarComponent)
class BarAdmin(admin.ModelAdmin):
    pass

# Inject BarComponent aspect into admin for Foo
@mark_safe
def has_bar(self, obj):
    try:
        return '<a href="%s">%s</a>' % (
            reverse(
                "admin:appb_barcomponent_change",
                args=(obj.bar_component.pk,),
            ),
            obj.bar_component.bar_type,
        )
    except ObjectDoesNotExist:
        return "-"


setattr(FooAdmin, "has_bar", has_bar)
setattr(FooAdmin.has_bar, "allow_tags", True)
setattr(FooAdmin.has_bar, "short_description", "Bar")
FooAdmin.list_display.append("has_bar")
FooAdmin.list_filter.append(("bar_component", admin.EmptyFieldListFilter))
FooAdmin.list_select_related.append("bar_component")

免责声明:代码是从我项目中的功能代码中删除的。因此,它尚未经过测试,但该结构适用于我的项目


推荐阅读