有没有办法在加载__init__.py时自动导入我文件夹中的所有模型?

问题描述 投票:0回答:2

在我的 Python 3.9、Django 3.2 项目中,我有这个通用文件夹结构

- manage.py
+ cbapp
    + models
        - __init__.py
        - vendor.py
        - user_preferences.py

在我的 init.py 文件中,我列出了所有模型条目...

from .vendor import Vendor
from .user_preferences import UserPreferences
...

每个模型类,例如供应商,有这样的总体结构

from django.db import models

class Vendor(models.Model): 
    ...

每次添加新模型时,我都必须在 init.py 文件中添加一行。 有什么方法可以编写我的 init.py 文件,以便它自动导入我添加到模型目录中的新文件?

python-3.x django django-models init
2个回答
1
投票

您正在寻找的是一些奇特的动态导入,例如这些

如果您的模型名称始终与模块名称相同,则 init.py 中的以下代码可能会起作用:

import os, glob

path = os.path.dirname(__file__)
modules = [os.path.basename(f)[:-3] for f in glob.glob(path + "/*.py")
           if not os.path.basename(f).startswith('_')]
stripped_path = os.path.relpath(path).replace('/', '.')
imports = {}
for module in modules:
    model_name = module.title().replace("_", "")
    imports[model_name] = getattr(__import__(stripped_path + "." + module, fromlist=[model_name]), model_name)
print(imports)
globals().update(imports)

0
投票

这应该可以工作,已使用 django 5.0 进行测试:

models/__init__.py

import glob
import importlib
import logging
import os

from django.db.models import Model

models_dir = os.path.dirname(__file__)
modules = glob.glob(os.path.join(models_dir, "*.py"))
module_names = [os.path.splitext(os.path.basename(m))[0] for m in modules if os.path.isfile(m)]
module_names = [name for name in module_names if name != "__init__"]

app_name = os.path.basename(os.path.dirname(os.path.dirname(__file__)))

imports = {}

for module_name in module_names:
    module_path = f"{app_name}.models.{module_name}"
    try:
        module = importlib.import_module(module_path)
    except ImportError as e:
        logging.warning(f"Failed to import {module_path}: {e}")
        continue

    for attribute_name in dir(module):
        attribute = getattr(module, attribute_name)
        if isinstance(attribute, type) and issubclass(attribute, Model) and attribute is not Model:
            imports[attribute_name] = attribute

globals().update(imports)
© www.soinside.com 2019 - 2024. All rights reserved.