0

私は2つのモデルを持っています:

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)

JSONで「SubCategory」オブジェクトを返すtastypieを使用してAPIを作成しています。カテゴリ ID が変更されたサブカテゴリのカウンターを含むすべての結果セットにカスタム フィールド「start_counter_of_category」を追加したい (「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 呼び出しを 2 回行ったときに、変数が前回の実行時の値を保持していることです。

API呼び出しが行われるたびに変数を再起動する方法はありますか?

解決:

変数を再初期化する

  • 呼び出された API がフィルタリング API の場合はbuild_filters
  • 呼び出された API が詳細 API の場合はget_detail

例(私の場合):

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

1 に答える 1

0

はい、各呼び出しの開始時に次のコードを実行するだけで、変数を再初期化できます (「再初期化」ではありません)。

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

しかし、これは悪い考えです。そもそもなぜこの変数はグローバルなのでしょうか? グローバル変数の要点は、モジュール内のすべてのオブジェクトによって共有され、モジュールの存続期間中存続することです。単一の API 呼び出しに対してローカルであり、その呼び出しの存続期間にわたって存続するものが必要な場合は、それらの特性を持つもののメンバーにします。適切なオブジェクトの初期化の一部としてメンバーを初期化します。その後、再初期化する必要はありません。

これが悪い考えである理由を確認するには: 2 つのクライアントが同時に接続し、両方が同じ API 呼び出しを行うとどうなりますか?

于 2012-11-07T08:30:17.347 に答える