簡體   English   中英

在裝飾器中更改 class 屬性

[英]Changing class attributes in decorator

我使用 django 作為一些 web 應用程序的框架。

我實現了自己的模型視圖,因為我在同一個視圖中有一些查詢集和序列化器。

為此,我需要自己實現所有的 CRUD 功能:

class Models1AndModel2View(mixins.CreateModelMixin,
                           mixins.RetrieveModelMixin, 
                           mixins.UpdateModelMixin,
                           mixins.DestroyModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    model1 = Model1.object.all()
    model1_serializer_class = Model1Seriazlizer

    model2 = Model2.object.all()
    model2_serializer_class = Model2Seriazlizer

    def refresh_querysets(func):
        def inner(self, *args, **kwargs):
            value = func(self, *args, **kwargs)
            self.model1 = Model1.object.all()
            self.model2 = Model2.object.all()
            return value
        return inner
 
   @refresh_querysets
   def list(self, request, *args, **kwargs):
       ...

   @refresh_querysets
   def retrieve(self, pk, request, *args, **kwargs):
       ...

   @refresh_querysets
   def update(self, pk, request, *args, **kwargs):
       ...

   @refresh_querysets
   def delete(self, pk, request, *args, **kwargs):
       ...

   @refresh_querysets
   def create(self, request, *args, **kwargs):
       ...


請注意,我在對象刷新之前調用裝飾器的 function。 我注意到在 function 調用之后設置的每個屬性實際上都沒有設置。

例如 - 我的一些測試:

  1. 列出所有模型 - 2 個模型實例
  2. 刪除其中一個
  3. 再次列出它們——仍然是 2 個模型實例(在模型 1 + 模型 2 中)
  4. 如果您查詢 model1 和 model2,您可以看到其中一個實例已按預期刪除,但 model1 未刷新。

我更改了裝飾器內部 function 的順序,它按預期工作。

    def refresh_querysets(func):
        def inner(self, *args, **kwargs):
            self.model1 = Model1.object.all()
            self.model2 = Model2.object.all()
            return func(self, *args, **kwargs)
        return inner

我相信您的問題是因為視圖是暫時的。

您將self.model1保存在根據請求銷毀和重新創建的視圖上。

如果 object 將被銷毀,則更新self毫無意義。

此外,您應該記住,在model1變量中設置的 model1 僅在 class 創建時初始化,而不是在實例創建時初始化,這意味着它將始終包含您導入相應模塊時的原始數據。

有 3 個選項可以解決它:

  1. 更改 function 裝飾器的順序,在運行self.model1之前設置 self.model1,或將其作為參數傳遞。

  2. __init__上更改model1 ,因此更改將應用於實例創建。

  3. 雖然不贊成,但 class 屬性model1現在等同於“全局類”(並且幾乎具有全局的所有缺點)。 您可以像這樣簡單地更改它:

     self.__class__.model1 = Model1.object.all()

    請記住,我認為這個 class 屬性甚至不應該存在。 如果它是不可變的,在實例創建時設置它更有意義。

無論哪種情況,我都不確定您是否希望在每次請求時轉儲整個 object / DB。 我不知道 django 是否巧妙地緩存object.all() (並在修改時更新緩存),但如果不是,那將是一個重大的減速。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM