【发布时间】:2012-11-07 07:39:58
【问题描述】:
我有两个模型:
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)
我正在使用tastepie 创建一个api,它以JSON 格式返回“SubCategory”对象。我想在每个结果集中添加一个自定义字段“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 时重新启动变量?
解决方案:
重新初始化变量
- 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 响应中,这些函数将被覆盖)
更好、最明显的解决方案
重新实例化 init 函数中的变量,如下所示:
def __init__(self,api_name=None):
self.API_SKU_VARS = {.....}
super(SKUResource,self).__init__(api_name)
【问题讨论】:
-
全局变量是糟糕的设计,特别是对于像 Python 这样具有良好命名空间的语言。
-
@PauloScardine 可能我的问题有点不对,我不希望变量是全局的。每次调用 API 时,我都需要重新初始化变量的值。
-
如果您不希望变量是全局的,请不要在全局范围内定义它。找出代表正确事物并具有正确生命周期的对象(它可能是
SubCategoryResource实例),并创建 API_SKU_VARS 作为该对象的成员(例如,通过在__init__方法中设置self.API_SKU_VARS)。跨度>
标签: python django api rest tastypie