How do I use a TabularInline with editable fields

2019-02-17 01:26发布

问题:

My models contain a many-to-many relationship. Measurements can be part of any number of DataSets.

# models.py
from django.db import models

class DataSet(models.Model):
    purpose = models.TextField()

class Measurement(models.Model):
    value = models.IntegerField()
    sets = models.ManyToManyField(DataSet, null=True, blank=True,
                         verbose_name="datasets this measurement appears in")

I want my admin interface to inlines Measurement fields in the DataSet admin like how a TabularInline works with a ForeignKey field. This is what I have so far:

# admin.py
from django.contrib import admin
from myapp.models import Measurement, DataSet

class MeasurementInline(admin.TabularInline):
    model = Measurement.sets.through

class DataSetAdmin(admin.ModelAdmin):
    inlines = [MeasurementInline]

admin.site.register(DataSet, DataSetAdmin)

Unfortunately, all I get are dropdown boxes with "+" buttons next to them that open up the Measurement admin. I want the actual Measurement field value to be exposed in the inline. I tried adding value to the list of fields on the MeasurementInline:

# admin.py    
class MeasurementInline(admin.TabularInline):
    model = Measurement.sets.through
    fields = ['value']

But that gives me an error: 'MeasurementInline.fields' refers to field 'value' that is missing from the form..

How do I expose editable fields for Measurement within the DataSet admin?

Notes: This is a simplified case; my real case has many fields in its Measurement model. It would be terribly tedious if the people using the admin interface had to open up a new window to enter data, especially since they will need to do some copying and pasting between fields as well.

Even in my real-world models, the data I want users to edit inline does NOT describe the relationship between the DataSet and the Measurement -- only the Measurement itself. I believe this makes an intermediary model unsuitable for my purposes.

回答1:

The short answer: you can't.

The long answer: you can't without significantly editing django's ModelAdmin. The InlineFormset factories that it uses are extremely limited, and cannot currently handle ManyToManyInlines. InlineModelAdmin objects are only supported with ForeignKeys.

Sorry.



回答2:

Well, not sure to really understand the project you are working on but if you want Measurement inlines in Dataset, you may want to put the relation in the Dataset model:

class DataSet(models.Model):
    purpose = models.TextField()
    measurements = models.ManyToManyField(DataSet, null=True, blank=True)

class Measurement(models.Model):
    value = models.IntegerField()

And in your admin.py, simply :

class MeasurementInline(admin.TabularInline):
    model = Measurement

class DataSetAdmin(admin.ModelAdmin):
    inlines = [MeasurementInline]

admin.site.register(DataSet, DataSetAdmin)

And using model = Measurement.sets.through looks odd to me.But maybe I totally missed the point ?