在Django Admin中使用内联的OneToOneField

时间:2014-01-02 18:56:04

标签: python django django-admin

我有 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定义的方向性,我无法进行内联。上面的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!

2 个答案:

答案 0 :(得分:3)

内部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)

答案 1 :(得分:3)

还有一个django插件可以在不必改变OneToOneField的方向的情况下进行内联: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)