问题
Given two related Django models A and B in a OneToMany relationship:
models.py
class A(models.Model):
name = models.CharField(max_length=5)
class B(models.Model):
name = models.CharField(max_length=5)
a = models.ForeignKey(A)
And given (potentially non-optimal) Tastypie resources:
api.py
class AResource(ModelResource):
bs = fields.ToManyField( 'projectname.api.BResource', 'bs', full = True)
class Meta:
queryset = A.objects.all()
class BResource(ModelResource):
a = fields.ToOneField( AResource, 'a', full = True)
class Meta:
queryset = B.objects.all()
Let's assume the database is empty so far. Now I have related external data, and would like to crowd the database it with both an instance of A and several instances of B.
What is the prettiest Tastypionic way to approach this problem? Is it possible to crowd both A and the Bs at once? Or do I need to crowd first A, and then crowd B supplying A's ID as the ForeignKey?
It would be great if someone could come up with an post example (using e.g. a python dictionary and httplib2, or curl).
Thanks a million.
回答1:
The solution is here . Use the related name for tastypie fields which automatically populate the reverse relationship while creating multiple objects at once. http://django-tastypie.readthedocs.org/en/v0.10.0/fields.html#tastypie.fields.RelatedField.related_name
RelatedField.related_name
Used to help automatically populate reverse relations when creating data. Defaults to None.
In order for this option to work correctly, there must be a field on the other Resource with this as an attribute/instance_name. Usually this just means adding a reflecting ToOneField pointing back.
Example:
class EntryResource(ModelResource):
authors = fields.ToManyField('path.to.api.resources.AuthorResource', 'author_set', related_name='entry')
class Meta:
queryset = Entry.objects.all()
resource_name = 'entry'
class AuthorResource(ModelResource):
entry = fields.ToOneField(EntryResource, 'entry')
class Meta:
queryset = Author.objects.all()
resource_name = 'author'
Use of related_name
do the task. it maps the objects of related fields and automatically populates the relations when creating data.
as you did full=True
on both side of your resources it will generate maximum recursion depth exceeded exception because both resources are full in each others.
回答2:
Here is one solution involving ManyToMany instead of OneToMany relationships:
models.py
class B(models.Model):
name = models.CharField(max_length=5)
class A(models.Model):
name = models.CharField(max_length=5)
bs = models.ManyToManyField(B)
api.py
class BResource(ModelResource):
class Meta:
queryset = B.objects.all()
resource_name = 'b'
class AResource(ModelResource):
bs = fields.ToManyField( BResource, 'bs', related_name = 'a', full = True, null=True)
class Meta:
queryset = A.objects.all()
resource_name = 'a'
curl
curl -v -H "Content-Type: application/json" -X POST --data '{"name":"a_name1", "bs":[{"name":"b_name1"}, {"name": "b_name2"}]}' http:<my_path>/api/a/
httplib2.py
A working example to post data via a python script using the httplib2 package is based on a neat and simple solution posted by warren-runk:
post_dict(
url='http:<my_path>/api/a/',
dictionary={
'name' : 'a_name1',
'bs' : [
{'name' : 'b_name1'},
{'name' : 'b_name1'},
]
}
)
However, now an additional table to relate A and B is created in the database. There might be better solutions based on the OneToMany relationship of A and B?
来源:https://stackoverflow.com/questions/11760973/posting-data-to-create-related-tastypie-resources-simultaneously