I need help on how to save the same (reference to an) object into a ManyToManyField.
For example I have models like this:
class Material(models.Model):
name = models.CharField(max_length=50)
class Compound(models.Model):
materials = models.ManyToManyField(Material)
In this example, the Compound
can be made of one or many different Material
s, and it also could be made from the same Material
twice (same id
in Material
model).
If I try to save through a ModelForm
, the second Material
is discarded because it has the same id
as the first Material
.
What is the best approach for this?
Thank you!
I would suggest doing this as per http://docs.djangoproject.com/en/dev/topics/db/models/#intermediary-manytomany
class Material(models.Model):
name = models.CharField(max_length=50)
class Compound(models.Model):
materials = models.ManyToManyField(Material, through='CompoundMaterials')
class CompoundMaterials(models.Model)
Material = models.ForeignKey(Material)
Compound = models.ForeignKey(Compound)
Quantity = models.IntegerField()
What am I doing here? Well, Django normally automatically generates an intermediary table for holding pairs of keys associating compounds to elements. In this case we're definiting it ourselves, but not only that, we're adding additional data to the relationship i.e. the quantity you speak of.
As an example usage, what you might do is this:
$ python manage.py shell
from project.app.models import *
oxygen = Material(name="oxygen")
hydrogen = Material(name="hydrogen")
water = Compound(name="water")
oxygen.save()
hydrogen.save()
water.save()
water_chemistry_oxygen = CompoundMaterials(Material=oxygen, Compound=Water, Quantity=1)
water_chemistry_hydrogen = CompoundMaterials(Material=hydrogen, Compound=Water, Quantity=2)
water_chemistry_oxygen.save()
water_chemistry_hydrogen.save()
Don't use a ManyToManyField
-
Create a new model (MaterialOfCompound
, for example), which holds two ForeignKey
s - one to a Material
record and one to a Compound
object.
Then, to find all materials a compound is made of, you could use:
[x.material for x in MaterialOfCompound.filter( compound = my_compound ) ]
or something similar.