簡體   English   中英

有沒有辦法動態創建 django 模型(類)?

[英]Is there a way to dynamically create django models(classes)?



我最近接到了一項具有挑戰性的任務,我們正在為客戶設計一個網站,我的老板希望我創建靈活的模型創建功能:這意味着他不希望我們對模型進行“硬編碼”,他告訴我們不是手動定義 Django 模型,而是在系統運行時創建它們。

例如,我們一開始沒有與我們的業務流程相關的模型,admin 用戶可以在我們的首頁定義一個表單的格式,稍后由一般用戶處理。 然后我們的后端接收來自前端的請求並使用提供的字段創建表單模型。 我發現我可以通過 type() 函數創建一個類,比如 type(class_name, (models.Model,), attrs),並且我確實通過這個函數獲得了新類。

但我想知道如何在我們的系統中保留這個類? 就像將這個新類保存到我的 models.py 中並進行遷移,以便我們的數據庫也擁有它

為了簡化這一點,我有偽代碼如下:

form_class_attrs = {
    'test_val': models.FloatField(),
    'test_name': models.CharField(),
    '__module__': __name__,
    }

def test(request):
    form_list = ['a', 'b']
    for form in form_list:
        form_class_name = "form_%s" % form
        attrs = form_class_attrs.copy()
        form_class = type(form_class_name, (models.Model,), attrs)

這里我在for循環中創建了兩個類,那么如何在for循環中持久化每個form_class並進行相應的遷移呢?

在調用test之后,動態創建的類應該等效於等效的聲明性模型 - 這是正確的。

為了讓 Django使用這些模型,必須將它們傳遞給將要使用的對象。 因此,您創建了一個form_class變量,它是test工廠函數的本地變量:您必須將此值返回到函數外部,並保留對每個創建的類的進程范圍引用,以便 Django 可以使用它。 (它不會在每次需要時調用該函數並重新創建模型,因為 Django 會創建一個與前一個模型沖突的新模型,至少在所需的 ORM 資源中如此)。

除此之外,您不應該為所有類只創建一次字段實例,並嘗試只對它們調用form_class_attrs.copy :這將嘗試在不同的類中重用相同的字段。 沿着這條線,您將不得不使用deepcopy - 但由於創建字段時生成的內部標識符,因此也有很大的可能性無法使用。 您必須重新創建字段實例(即為每個動態類實際調用.CharField() 。最簡單的方法(不是最好的)就是將 attr_fields 聲明移動到您的 for 循環內。

調用工廠函數一次,並返回列表或字典中的所有模型就足以用於模型使用 - 但不適用於遷移目的(包括類創建) - Django 中的遷移機制可能取決於導入所有模塊並檢查現有模型:我不確定這一點,但我認為這取決於在模塊命名空間中查找模型,而不僅僅是“創建”。 因此,它們必須在導入時添加到模塊命名空間中——即使它們沒有被使用。 在 Python 中,這可以通過更新globals()調用返回的字典來完成。

總而言之,這應該適合您:



def test():
    form_list = ['a', 'b']
    forms = {}
    for form in form_list:
        attrs = {
            'test_val': models.FloatField(),
            'test_name': models.CharField(),
            '__module__': __name__,
        }
        form_class_name = f"form_{form}" 
        form_class = type(form_class_name, (models.Model,), attrs)
        forms[form_class_name] = form_class

all_forms = test()
globals().update(all_forms)

暫無
暫無

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

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