Django中使用f-string拼接exec代码出现缩进错误如何解决?
错误原因
- 缩进不规范:你定义的f-string三引号模板里,三个类的定义行缩进不一致:第一个类顶格编写,后续两个类前面多了4个空格,类内部的字段缩进也没有统一,直接触发Python缩进校验错误。
- 数据库查询时机错误:在models.py顶层直接执行
class_site.objects.all()查询,Django启动阶段ORM、数据库连接还未初始化完成,会额外触发数据库访问错误。 - 动态模型未注册:默认exec生成的类仅存在于exec的局部作用域,不会被注册到当前models模块,Django的迁移系统、ORM都无法识别这些动态生成的模型,后续也无法做数据库操作。
修复实现
1. 修正f-string模板与exec调用
统一模板缩进,添加模型Meta属性指定所属应用,执行时传入当前模块全局作用域:
from django.db import models from SFC.models import class_site from django.db.models.signals import post_migrate from django.dispatch import receiver # 动态生成模型的逻辑放到信号回调中 @receiver(post_migrate) def generate_dynamic_models(sender, **kwargs): # 只在WT应用迁移完成后执行 if sender.name != 'WT': return for i in class_site.objects.all(): model_prefix = i.school_name + i.Class code = f''' class {model_prefix}subject(models.Model): subject = models.CharField('科目名', max_length=10) class Meta: app_label = 'WT' class {model_prefix}WorkType(models.Model): subject = models.ForeignKey({model_prefix}subject, on_delete=models.CASCADE) work_name = models.CharField('功課名稱', max_length=10, default='習作') common_name = models.CharField('功課俗名', max_length=10, default='國習') class Meta: app_label = 'WT' class {model_prefix}ExamType(models.Model): subject = models.ForeignKey({model_prefix}subject, on_delete=models.CASCADE) work_name = models.CharField('考試名稱', max_length=10, default='大卷') common_name = models.CharField('功課俗名', max_length=10, default='國卷') class Meta: app_label = 'WT' ''' # 传入globals()将生成的类注册到当前模块全局作用域 exec(code, globals())
2. 注册信号
在WT应用的apps.py中添加信号注册,确保启动时加载信号回调:
from django.apps import AppConfig class WtConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'WT' def ready(self): # 导入信号处理函数 import WT.models
3. 后续操作说明
每次新增class_site实例后,需要重新执行python manage.py makemigrations WT和python manage.py migrate命令,生成新班级对应的数据库表。
内容的提问来源于stack exchange,提问作者黑殼鐵hekote
相关产品推荐
相关产品推荐

