Posting data to create related Tastypie resources simultaneously?

岁酱吖の 提交于 2019-12-12 09:19:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!