簡體   English   中英

在 Django 管理員中,添加通用關系的內聯

[英]In a Django admin, add an inline of a generic relation

這是我的簡化模型:

from django.contrib.contenttypes.fields import (
    GenericForeignKey, GenericRelation)
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Thing(models.Model):
    '''
    Our 'Thing' class
    with a link (generic relationship) to an abstract config
    '''

    name = models.CharField(
        max_length=128, blank=True,
        verbose_name=_(u'Name of my thing'))

    # Link to our configs
    config_content_type = models.ForeignKey(
        ContentType,
        null=True,
        blank=True)
    config_object_id = models.PositiveIntegerField(
        null=True,
        blank=True)
    config_object = GenericForeignKey(
        'config_content_type',
        'config_object_id')


class Config(models.Model):
    '''
    Base class for custom Configs
    '''
    class Meta:
        abstract = True

    name = models.CharField(
        max_length=128, blank=True,
        verbose_name=_(u'Config Name'))

    thing = GenericRelation(
        Thing,
        related_query_name='config')


class FirstConfig(Config):
    pass


class SecondConfig(Config):
    pass

這是管理員:

from django.contrib import admin
from .models import FirstConfig, SecondConfig, Thing


class FirstConfigInline(admin.StackedInline):
    model = FirstConfig


class SecondConfigInline(admin.StackedInline):
    model = SecondConfig


class ThingAdmin(admin.ModelAdmin):
    model = Thing

    def get_inline_instances(self, request, obj=None):
    '''
    Returns our Thing Config inline
    '''
        if obj is not None:
            m_name = obj.config_object._meta.model_name
            if m_name == "firstconfig":
                return [FirstConfigInline(self.model, self.admin_site), ]
            elif m_name == "secondconfig":
                return [SecondConfigInline(self.model, self.admin_site), ]
        return []


admin.site.register(Thing, ThingAdmin)

到目前為止,我有一個Thing對象和一個鏈接在一起的FirstConfig對象。 代碼被簡化:在一個不相關的部分,我設法在創建Thing創建我的抽象Config並設置正確的content_type / object_id

現在我想在我的ThingAdmin看到這個FirstConfig實例作為內聯( FirstConfigInline )。

我嘗試使用django.contrib.contenttypes.admin.GenericStackedInline ,盡管它不適用於我當前的模型設置。
我嘗試使用我的FirstConfigInlinefk_name參數。
此外,如您所見,我嘗試在我的Config模型上使用“事物” GenericRelation屬性,但沒有成功。

關於如何繼續正確設置管理員的任何想法?

根據Django Docs,如果 ct_fk_field 和 ct_field 已從默認值更改,則必須定義它們。 因此,將 ct_field 設置為 config_content_type 可能就足夠了。

希望它有效!

編輯:這些值必須在內聯中聲明:

class SecondConfigInline(admin.StackedInline):
    model = SecondConfig
    ct_fk_field = "config_object_id"
    ct_field = "config_content_type"

編輯2:

我剛剛意識到我的假設有誤。 通常你應該在內聯模型上聲明外鍵。 根據您的代碼的其余部分,您可以刪除 Thing 上的通用外鍵 + Config 上的 genericRelation,並在 Config-Basemodel 上聲明一個正常的外鍵。

這個問題很老了,但無論如何我都會試一試。

我認為解決方案取決於您打算在Thing和您的Config子類之間創建什么樣的關系。

多對一/一對多

它目前的設置方式,看起來像是一個多對一的關系:每個Thing指向單個Config子類,而許多Thing可以指向同一個Config子類。 由於通用關系,每個Thing可以指向不同的模型(不一定是Config子類,除非您做一些額外的工作)。

在這種情況下,我想將內聯放在Config的管理員上會更有意義。 也就是說,建立一個GenericStackedInlineThing (它具有GenericForeignkey ),以及內嵌添加到ConfigAdmin ,然后你就可以使用所有Config的子類。 另請參見下面的示例。 然后通用內聯將自動設置正確的content_typeobject_id

多對多

在另一方面,如果你正在尋找之間的許多一對多關系Thing ,並且每個Config的子類,那么我會在移動GenericForeignkey到一個單獨的許多一對多表(可以稱之為ThingConfigRelation )。

一段代碼一千多字,讓我們把你的Thing類拆分如下:

class Thing(models.Model):
    name = models.CharField(max_length=128)


class ThingConfigRelation(models.Model):
    thing = models.ForeignKey(to=Thing, on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, null=True, blank=True,
                                     on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField(null=True, blank=True)
    config_object = GenericForeignKey(ct_field='content_type',
                                      fk_field='object_id')

現在,向ThingAdmin添加內聯是ThingAdmin 以下是適用於關系雙方的管理員的基本示例:

from django.contrib import admin
from django.contrib.contenttypes.admin import GenericStackedInline
from .models import Thing, FirstConfig, SecondConfig, ThingConfigRelation


class ConventionalTCRInline(admin.StackedInline):
    model = ThingConfigRelation
    extra = 0


class GenericTCRInline(GenericStackedInline):
    model = ThingConfigRelation
    extra = 0


class ThingAdmin(admin.ModelAdmin):
    inlines = [ConventionalTCRInline]


class ConfigAdmin(admin.ModelAdmin):
    inlines = [GenericTCRInline]


admin.site.register(Thing, ThingAdmin)
admin.site.register(FirstConfig, ConfigAdmin)
admin.site.register(SecondConfig, ConfigAdmin)

請注意,我們使用傳統的直排的ForeignKey關系的-側(即ThingAdmin ),而我們使用的通用的內嵌GenericForeignKey -側(在ConfigAdmin )。

一個棘手的問題是過濾ThingAdmin上的content_typeobject_id字段。

...完全不同的東西:

另一種選擇可能是擺脫了GenericForeignKey干脆使用某種類型的單表繼承的實現與普通的舊ForeignKeys而是有點像這樣

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM