Reputation: 2259
I have a situation where I'm trying to create a quick and easy admin interface for composers to list the instruments in a piece of music. What I am looking for is a single entity, an Instrumentation, which defines a particular combination of instruments. For example, a saxophone quartet might consist of:
but it also might consist of two altos, tenor and bari instread. The problem gets worse when you try to add an entire section (like 1st violins--as many as 18 members).
The initial model I came up with looks like this:
class Work(Post):
authors = models.ManyToManyField(Individual)
title = models.CharField(max_length=255)
subtitle = models.CharField(max_length=255, blank=True)
program_notes = models.TextField(blank=True)
notes = models.TextField(blank=True)
media = models.ManyToManyField('Upload')
class Composition(Work):
instrumentation = models.ForeignKey('Instrumentation')
class Instrumentation(models.Model):
forces = models.ManyToManyField(Instrument)
types = models.ManyToManyField('InstrumentationType')
class InstrumentationType(models.Model):
type = models.CharField(max_length=255)
variation = models.SmallIntegerField(default=0)
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
I plan to later map each instrument in the piece to a performer in a rehearsal, concert, etc., so it's more than a simple count that I need. If I were doing this without django (i.e. just SQL and database design), I would have a mapping table with
Instrumentation :
It looks like Django is creating this exact situation for me in the database, but for some reason the framework needs type
, composition_id
and instrument_id
to be unique together. The admin interface (multiselect box) also makes it clear that having multiple similar entries isn't how the many to many field was designed to work. So how do I achieve this? Is there an established workaround for this?
Upvotes: 0
Views: 2257
Reputation: 2259
The chosen answer to this question solves it. I needed to explicitly define the mapping table and then use the admin inline feature to fix the interface.
models.py:
class Instrumentation(models.Model):
forces = models.ManyToManyField(Instrument, through='InstrumentationForces')
types = models.ManyToManyField('InstrumentationType')
class InstrumentationForces(models.Model):
instrument = models.ForeignKey(Instrument)
instrumentation = models.ForeignKey(Instrumentation)
admin.py:
class InstrumentInline(admin.TabularInline):
model = InstrumentationForces
extra = 3
class InstrumentationAdmin(admin.ModelAdmin):
filter_horizontal = ('types',)
inlines = (InstrumentInline,)
admin.site.register(Instrumentation, InstrumentationAdmin)
Upvotes: 2