2012-11-07 28 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

相关问题