【问题标题】:Use OneToOneField inlined in Django Admin在 Django Admin 中使用内联 OneToOneField
【发布时间】:2014-01-02 18:56:04
【问题描述】:

我有 DataFile 模型,其中有 LogOutput 对象。 DataFile 对象将有一个 LogOutput。对于属于 DataFile 的任何 LogOutput,它将只属于单个 DataFile。其他模型也有 LogOutput 对象。

因为它们是一对一的,除了 LogOutputs 可以属于 DataFiles 以外的东西(例如,Suites 也有它们-- 请参见下面的代码)我认为正确的做法是在 DataFile 中定义一个 OneToOneField,即 LogOutput

models.py

class LogOutput(models.Model):
    raw = models.TextField()

class DataFile(models.Model):
    name = models.CharField()#etc.
    logoutput = models.OneToOneField(LogOutput)

class Suite(models.Model):
    # Many Suites will have the same datafile:
    datafile = models.ForeignKey(DataFile)

    # Each Suite has a unique LogOutput different from the DataFile's
    # and as with the DataFile, that LogOutput will have just one Suite
    logoutput = models.OneToOneField(LogOutput)

现在,当我在 Admin 视图中查看 DataFile 时,我想查看 LogOutput,所以我想我只是内联它。

admin.py

class LogOutputInline(admin.TabularInline):
    model = LogOutput

class DataFileAdmin(admin.ModelAdmin):
    search_fields = ['name']
    inlines = [LogOutputInline]

admin.site.register(DataFile, DataFileAdmin)

似乎由于 OneToOneField(s) 定义位置的方向性,我无法进行内联。上面的 admin.py 给了我:

<class 'trial.models.LogOutput'> has no ForeignKey to <class 'trial.models.DataFile'>

这当然是真的,但我看不出它是如何相关的,因为 DataFile 有一个(并且只有一个)LogOutput,而这反过来,只属于这一个DataFile

我阅读了Question 1744203,但解决方案是扭转关系的方向。我认为我不能这样做,因为其他对象(Suites)也有 LogOutputs

而且,如果重要的话,这是在 Django 1.5 中。

我的问题是:我需要做什么才能在 DataFile 的 管理页面上显示内联 LogOutput? (或者我是否考虑使用 OneToOneField 需要修改?)

TIA!

【问题讨论】:

  • 你试过fk_name吗? fk_name = "日志输出"
  • 我不熟悉它。我去看看。
  • 这似乎是同样的问题。具体来说,方向性仍被假定为另一种方式:LogOutputInline.fk_name' 指的是模型'trial.LogOutput 中缺少的字段''
  • 似乎是正确的行为:code.djangoproject.com/ticket/18059
  • @Anto - 问题本身已经提到 Django Admin: OneToOne Relation as an Inline? 可能重复,以及为什么它不适用。

标签: python django django-admin


【解决方案1】:

还有一个 django 插件可以进行内联,而无需反转 OneToOneField(s) 的方向:django_reverse_admin

您需要将 django_reverse_admin 添加到您的 requirements.txt:

-e git+https://github.com/anziem/django_reverse_admin.git#egg=django_reverse_admin

然后导入:

admin.py

from django_reverse_admin import ReverseModelAdmin

# don't need to define an inline for LogOutput

class DataFileAdmin(ReverseModelAdmin):
    search_fields = ['name']
    inline_reverse = ['logoutput']
    inline_type = 'tabular'  # or could be 'stacked'

admin.site.register(DataFile, DataFileAdmin)

【讨论】:

    【解决方案2】:

    内部 ORM 和管理员非常聪明,但是在 OOP 与表结构相冲突的情况下,事情可能有点不精确。我建议使用 abstract base class 给 ORM 一些提示,如下所示:

    class LogOutput(models.Model):
        raw = models.TextField()
    
        class Meta:
            abstract = True
    
    class DataFileLogOutput(LogOutput):
        pass
    
    class SuiteFileLogOutput(LogOutput):
        pass
    
    class DataFile(models.Model):
        name = models.CharField()#etc.
        logoutput = models.OneToOneField(DataFileLogOutput)
    
    class Suite(models.Model):
        # Many Suites will have the same datafile:
        datafile = models.ForeignKey(DataFile)
    
        # Each Suite has a unique LogOutput different from the DataFile's
        # and as with the DataFile, that LogOutput will have just one Suite
        logoutput = models.OneToOneField(SuiteLogOutput)
    

    【讨论】:

    • 是的,我希望避免这种情况,但我可以看到我的心智模型可能与 ORM 管理 SQL 的方式不一致。谢谢指点!
    • 这如何允许在管理员中反转日志输出 OneToOne 关系? (关于管理员如何解决关系的方向性)
    • 当 havong auth.User(django 的系统用户)作为模型时这是不可能的。我无法改变这一点(没有太多麻烦)。
    猜你喜欢
    • 2014-06-11
    • 2012-04-13
    • 2018-07-23
    • 2014-10-23
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2020-04-16
    相关资源
    最近更新 更多