2012-11-07 32 views
0

我有兩個型號:Django Tastypie:每次進行api調用時如何啓動變量?

class Category(models.Model): 
    name = models.CharField(max_length=50) 

class SubCategory(models.Model): 
    sex = models.CharField(choices=SEX, blank=True, max_length=5) 
    name = models.TextField(blank=True) 
    category = models.ForeignKey(Category) 
    def __unicode__(self): 
     return u'%s' % (self.name) 

我創建使用tastypie返回的JSON我 「子類別」 對象的API。我想在每個結果集中添加一個自定義字段「start_counter_of_category」,其中包含類別id更改的子類別的計數器(在「category_id」字段中排序時)

該算法非常簡單,類似於「脫水」功能:

API_SKU_VARS = { 
    'COUNTER'  : 1, 
    'FIRST_ELEMENT' : 1, 
    'PREV_CATEGORY' : 1 
} 


class SubCategoryResource(ModelResource): 
    start_counter_of_category = fields.IntegerField(readonly=True) 
    category = fields.ForeignKey(CategoryResource,'category') 
    class Meta: 
     queryset = SubCategory.objects.all() 
     resource_name = 'subcategory' 
     filtering = { 
      'id' : ALL, 
      'name' : ALL, 
      'category': ALL_WITH_RELATIONS, 
     } 
     ordering = ['id','name','category'] 
     serializer = Serializer(formats=['json']) 
    def dehydrate(self, bundle): 
     if API_SKU_VARS['PREV_CATEGORY'] != bundle.data['category']: #if the category of the current bundle is not equal to the category of the previous bundle, we update the ['PREV_CATEGORY'] 
      API_SKU_VARS['FIRST_ELEMENT']=API_SKU_VARS['COUNTER'] #update the ['FIRST_ELEMENT'] with the counter of the current bundle 
      API_SKU_VARS['PREV_CATEGORY'] = bundle.data['category'] 
     API_SKU_VARS['COUNTER'] = API_SKU_VARS['COUNTER']+1 #for every bundle passed, we update the counter 
     bundle.data['start_counter_of_category']=API_SKU_VARS['FIRST_ELEMENT'] 
     return bundle.data 
    serializer = Serializer(formats=['json']) 

它適用於啓動服務器後的第一次運行。可以預見的是,問題當然是,我第二次進行api調用時,變量保留了他們在前一次運行中的值。

任何想法如何在每次調用api時重新啓動變量?

SOLUTION:

重新initialte變量在

  • build_filters如果調用所述API是一個過濾API
  • get_detail如果調用該API是一個細節API

例(對我來說):

def build_filters(self, filters=None): 
     if filters is None: 
      filters = {} 
     orm_filters = super(SubCategoryResource, self).build_filters(filters) #get the required response using the function's behavior from the super class 
     self.API_SKU_VARS = { 
      'PREV_CATEGORY':1, 
      'COUNTER':1, 
      'FIRST_ELEMENT':1, 
     } 
     return orm_filters 

(這些函數的過度纏身,如果你想要的任何自定義邏輯應用到API響應)

更好,最明顯的解決方案

重新實例變量在初始化功能,這樣的事情:

def __init__(self,api_name=None): 
    self.API_SKU_VARS = {.....} 
    super(SKUResource,self).__init__(api_name) 
+1

全局變量是不好的設計,特別是對於像Python這樣名字空間很好的語言。 –

+0

@PauloScardine可能我的問題有點不對,我不希望變量是全局的。每次進行API調用時,我都需要重新初始化變量的值。 –

+0

如果您不希望變量是全局變量,請不要在全局範圍內定義變量。找出哪個對象代表正確的事物並且擁有正確的生命週期(可能是'SubCategoryResource'實例),並創建API_SKU_VARS作爲該對象的成員(例如,通過在__init__方法中設置self.API_SKU_VARS)。 – abarnert

回答

0

是的,你可以重新初始化只是在每次通話開始運行這段代碼(不是「重新開始」)的變量:

API_SKU_VARS['COUNTER'] = 1 
API_SKU_VARS['PREV_CATEGORY'] = 1 
API_SKU_VARS['FIRST_ELEMENT'] = 1 

但是,這是一個壞主意。爲什麼這個變量是全球性的?全局變量的全部要點是它由模塊中的所有對象共享,並在模塊的整個生命週期中保持不變。如果你想要一個API調用本地的東西,並且在該調用的整個生命週期內存在,請使它成爲具有這些特性的東西的成員。初始化該成員作爲初始化適當對象的一部分。那麼不需要重新初始化它。

看看爲什麼這是一個糟糕的主意:如果兩個客戶端併發連接並且都進行相同的API調用會發生什麼?

+0

感謝您的回答。非常有效的疑問在最後。是的,這是一個巨大的問題。但是,我目前的情況並不要求併發性。如果在併發用戶的情況下知道如何有效地做到這一點,也是非常好的。 即將到來的變量的重新初始化,這是我無法專門在tastypie模塊中做的重新初始化。試着在resources.py文件中做這件事,但這不起作用。 –

+0

如果你不想併發,你爲什麼要編寫一個Web服務?爲什麼不寫一個腳本來在本地運行,並拋棄所有不必要的複雜性?幾乎所有必須上網的東西都必須處理併發。無論如何,有效地處理成員變量的方法是使它們成爲成員變量,而不是用全局變量僞造它們。但效率只是一個副作用,以正確的方式來做這件事的原因並不在於它稍微快一點,而是它實際上起作用。 – abarnert

相關問題