I have searched about this issue a lot and gone through a bunch of related questions on Stack Overflow, but there doesn't seem to be a definitive answer about how to implement many-to-many relationships "through" an intermediate model (or maybe I missed it).
I have a model named Sample which has a many-to-many relationship with Region. There is an intermediate model which connects the two, named SampleRegion. I am currently not saving any extra information on the intermediate model, but I might in the future.
Here are my models:
class Sample(models.Model):
sample_id = models.BigIntegerField(primary_key=True)
description = models.TextField(blank=True)
objects = models.GeoManager()
regions = ManyToManyField(Region, through='SampleRegion')
class Meta:
db_table = u'samples'
def save(self, **kwargs):
# Assign a sample ID only for create requests
if self.sample_id is None:
try: id = Sample.objects.latest('sample_id').sample_id + 1
except Sample.DoesNotExist: id = 1
self.sample_id = id
super(Sample, self).save
class Region(models.Model):
name = models.CharField(max_length=100, unique=True)
def __unicode__(self):
return self.name
class Meta:
db_table = u'regions'
class SampleRegion(models.Model):
sample = models.ForeignKey('Sample')
region = models.ForeignKey(Region)
class Meta:
unique_together = (('sample', 'region'),)
db_table = u'sample_regions'
And here is one approach I took to write the resources. It's not correct, and I am not able to figure out the right way of doing it:
class SampleResource(ModelResource):
regions = fields.ToManyField("tastyapi.resources.RegionResource",
"regions")
class Meta:
queryset = models.Sample.objects.all()
allowed_methods = ['get', 'post', 'put', 'delete']
authentication = ApiKeyAuthentication()
authorization = ObjectAuthorization('tastyapi', 'sample')
excludes = ['user', 'collector']
filtering = {
'version': ALL,
'sesar_number': ALL
}
validation = VersionValidation(queryset, 'sample_id')
def hydrate_regions(self, bundle):
# code to create a new SampleRegion object by getting a list of
# regions from bundle.data['regions']
class RegionResource(ModelResource):
class Meta:
queryset = models.Region.objects.all()
allowed_methods = ['get']
resource_name = "region"
filtering = {
'region': ALL,
}
This is how I making a POST request:
post_data = {
'regions': ["/tastyapi/v1/region/2/"],
'description': 'Created by a test case',
}
client.post('/tastyapi/v1/sample/', data = post_data,
authentication = credentials, format = 'json')
This request doesn't work because bundle.data['regions'] is None
by the time
it reaches hydrate_regions
.
Does anybody have any advice on how I should go about implementing this scenario?