2012-08-01 50 views
2

给定两个有关Django模型一对多关系:发布数据以同时创建相关的Tastypie资源?

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) 

并给予(潜在地非最佳)Tastypie资源:

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() 

让我们假设到目前为止数据库是空的。现在我有相关的外部数据,并且希望将数据库与A的实例和几个B的实例相关联。

什么是最好的Tastypionic方法来解决这个问题?是否有可能同时拥挤A和B?或者,我需要首先挤满A,然后挤B将A的ID作为外键?

如果有人能拿出一个帖子的例子(例如使用python字典和httplib2,或curl),这将是很好的。

非常感谢。

回答

1

这里是一个解决方案,涉及多对多而不是一对多关系:

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 -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

工作示例通过使用httplib2的包一个Python脚本发布数据是基于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'}, 
     ] 
    } 
) 

然而,现在在数据库中创建一个关联A和B的附加表。 A和B的关系可能会有更好的解决方案吗?

2

解决方法就在这里。使用tastypie字段的相关名称,可以在创建多个对象的同时自动填充反向关系。 http://django-tastypie.readthedocs.org/en/v0.10.0/fields.html#tastypie.fields.RelatedField.related_name

RelatedField.related_name

用于帮助自动创建数据时填充反向关系。默认为None。

为了使此选项正常工作,其他资源上必须有一个字段,并将其作为属性/ instance_name。通常这只是意味着添加反射的ToOneField指向。

例子:

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' 

使用related_name做任务。它映射相关字段的对象并在创建数据时自动填充关系。

就像您在资源的两侧执行full=True一样,它会生成超出最大递归深度的异常,因为两个资源在其他资源中都是完整的。

相关问题