I'd like to create a relationship for Django ORM in which I can add objects from a Set, with data associated in that relationship, but only add each item once to any given container. I mean to use the term Set, defined as follows:
A set is a well defined collection of distinct objects.
Each item in the set, SetItem, is unique within the set. I am ensuring that they are unique in this case by having its fields defined with the unique=True
kwarg at the class definition. The container for these items, SetItemContainer, has a relationship to the SetItem which permit the container to associate some data with the SetItemRelationship.
It is a ManyToMany Relationship, but with a twist that there can only be one of each SetItem A
, B
, C
, or D
in any individual SetContainer. Using the Pizza and Toppings analogy, Each Pizza can have any amount of Toppings, Every Topping can as many Pizzas as want it, but in this case No Topping can be added to any individual Pizza more than once, i.e. You can't add two "Anchovies" Toppings on any individual Pizza (That's what the "data" in the SetItemRelationship is for).
You can see a proposed pattern in this app's models.py
from django.db import models
class SetItem(models.Model):
text = models.CharField(max_length=32, unique=True)
def __unicode__(self):
return self.text
class SetContainer(models.Model):
label = models.CharField(max_length=64)
set_items = models.ManyToManyField(SetItem, through='SetItemRelationship')
def __unicode__(self):
return self.label
class SetItemRelationship(models.Model):
container = models.ForeignKey(SetContainer)
item = models.ForeignKey(SetItem)
data = models.PositiveSmallIntegerField()
def __unicode__(self):
return "{:s} contains {:s}".format(self.container.label, self.item.text)
This model relationship permits me to create multiple SetContainer objects, each of which have their own instances of the SetItem objects with data associated with them. However, I would like to be limited to only adding one instance of each relationship. I've attempted to figure this out, using the following admin.py:
from django.contrib import admin
from .models import SetItem, SetContainer, SetItemRelationship
class SetInline(admin.TabularInline):
model = SetItemRelationship
class SetContainerAdmin(admin.ModelAdmin):
inlines = [SetInline]
admin.site.register(SetContainer, SetContainerAdmin)
admin.site.register(SetItem)
As you can see in the following screen cap, I am capable of adding two SetItemRelationships to the Unique SetItem which has SetItem.text == A
How can I set up a relationship to prevent that addition, and ideally, to prevent the drop down from containing any of the previously used SetItems when adding a new SetItemRelationship.
Edit: I added an explanatory paragraph including the Pizza and Toppings analogy, modified to help explain this relationship.