I have DataFile models which have LogOutput objects. A DataFile object will have a single LogOutput. For any LogOutput that belongs to a DataFile, it will only belong to a single DataFile. Other models also have LogOutput objects.
Since they are one-to-one, except that LogOutputs can belong to things other than DataFiles (eg. Suites have them too -- see code below) I thought the right thing to do would be to have a OneToOneField defined in DataFile that is the 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)
Now, when I look at a DataFile in the Admin view, I want to see the LogOutput, so I thought I would just inline it.
admin.py:
class LogOutputInline(admin.TabularInline):
model = LogOutput
class DataFileAdmin(admin.ModelAdmin):
search_fields = ['name']
inlines = [LogOutputInline]
admin.site.register(DataFile, DataFileAdmin)
It appears that because of the directionality of where the OneToOneField(s) are defined, I can't do the inlining. The above admin.py gives me:
<class 'trial.models.LogOutput'> has no ForeignKey to <class 'trial.models.DataFile'>
Which, of course is true, but I don't see how it's relevant, because a DataFile has one (and only one) LogOutput which, in turn, belongs to only this one DataFile.
I read Question 1744203 but the solution there was to reverse the direction of the relationship. I don't think I can do that because other objects (Suites) also have LogOutputs.
And, if it matters, this is in Django 1.5.
My question is: What do I need to do in order to display the inline LogOutput on the DataFile's admin page? (Or is my thinking about the use of a OneToOneField in need of revision?)
TIA!
There's also a django add-on to get inlining without having to reverse the direction of the OneToOneField(s): django_reverse_admin
You'll need to add django_reverse_admin to your requirements.txt:
-e git+https://github.com/anziem/django_reverse_admin.git#egg=django_reverse_admin
Then import it:
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)
The internal ORM and admin are pretty smart, but where OOP runs up against table structure, things can be a bit imprecise. I'd recommend giving the ORM a little hint by using an abstract base class like this:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With