[英]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
,盡管它不適用於我當前的模型設置。
我嘗試使用我的FirstConfigInline
的fk_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
的管理員上會更有意義。 也就是說,建立一個GenericStackedInline
的Thing
(它具有GenericForeignkey
),以及內嵌添加到ConfigAdmin
,然后你就可以使用所有Config
的子類。 另請參見下面的示例。 然后通用內聯將自動設置正確的content_type
和object_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_type
和object_id
字段。
另一種選擇可能是擺脫了GenericForeignKey
干脆使用某種類型的單表繼承的實現與普通的舊ForeignKeys
而是有點像這樣。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.