2014-09-04 60 views
4

我正在使用Tastypie爲Django應用程序創建REST API,並希望能夠在一個POST中創建新對象和相關對象。相關對象由用於查找它們的名稱指定,如果找不到名稱,我想創建新對象。如何使POST get_or_create相關的資源tastypie

鑑於Django模型是這樣的:

class Product(Model): 
    name = CharField(max_length=32) 

class Release(Model): 
    product = ForeignKey(to=Product, related_name='releases') 
    version = CharField(max_length=32) 

而且這些Tastypie資源:

class ProductResource(ModelResource): 
    class Meta: 
     queryset = Product.objects.all() 
     resource_name = 'product' 

class ReleaseResource(ModelResource): 
    class Meta: 
     queryset = Release.objects.all() 
     resource_name = 'release' 

    def hydrate_product(self, bundle): 
     """Replace product name with id of existing/created one.""" 
     product = Product.objects.get_or_create(name=bundle.data['product']) 
     bundle.data['product'] = product.id 
     return bundle 

和一個空數據庫

當我這個POST數據到我tastypie REST API:

POST /api/release { 
    "product": "Cool Widget", 
    "version": "1.2.3", 
} 

然後我想創建這些模型對象:

product = Product(name="Cool Widget") 
release = Release(product=product, version="1.2.3") 

但我得到一個例外是這樣的:

IntegrityError: null value in column "product_id" violates not-null constraint 
DETAIL: Failing row contains (1, null, 1.2.3). 

和()方法不叫hydrate_product。

當我這個類屬性添加到R​​eleaseResource:

product = fields.ToOneField(ProductResource, 'product') 

然後我得到的是這樣的:

NotFound: An incorrect URL was provided 'Cool Widget' for the 'ProductResource' resource. 

如何在捆綁與創建的URI更換產品名稱/現有產品對象具有該名稱?

回答

3

我認爲我的錯誤在於試圖修改關係字段的目的。如果我的資源實際包含它們,它們應該保持正常工作。

我應該聲明ReleaseResource.productCharField和實施Release.obj_create創建新Release時使用Product.objects.get_or_create的相關Product對象。

class ReleaseResource(ModelResource): 
    product = CharField(attribute='product__name') 

    class Meta: 
     queryset = Release.objects.all() 
     resource_name = 'release' 

    def obj_create(self, bundle, **kwargs) 
     product = Product.objects.get_or_create(name=bundle.data['product'])[0] 
     super(ModelResource, self).obj_create(bundle, product=product, **kwargs) 

這似乎不夠清晰的DOCO是沒有關係字段填充自動一個ModelResource,你必須明確地聲明所有關係領域,而不僅僅是那些顛倒。

0

這裏:

class ReleaseResource(ModelResource): 
    class Meta: 
     queryset = Release.objects.all() 
     resource_name = 'release' 

    def hydrate_product(self, bundle): 
     """Replace product name with id of existing/created one.""" 
     product = Product.objects.get_or_create(name=bundle.data['product']) 
     bundle.data['product'] = product.id 
     return bundle 

hydrate_product因爲hydrate_*基礎上產生Tastypie領域相關的地方不存在默認情況下不會被觸發。

我不是100%它肯定,但我會嘗試這樣的:

class ReleaseResource(ModelResource): 
    class Meta: 
     queryset = Release.objects.all() 
     resource_name = 'release' 

    def hydrate(self, bundle): 
     """Replace product name with id of existing/created one.""" 
     product = Product.objects.get_or_create(name=bundle.data['product']) 
     bundle.obj.product = product 
     return bundle 

注:我給你的產品對象bundle.obj.product

+0

謝謝,最終我發現最簡單的解決方案是聲明CharField的名稱和get_or_create obj_create實現中的相關對象。看到我的答案在這個線程。 – quantoid 2014-09-07 22:10:29