Django 启动代码(如初始缓存)冲突 makemigrations。操作错误没有这样的列表

Posted

技术标签:

【中文标题】Django 启动代码(如初始缓存)冲突 makemigrations。操作错误没有这样的列表【英文标题】:Django start-up code (like initial caching) conflicts makemigrations. Operational Errors no such columns tables 【发布时间】:2020-05-04 22:30:49 【问题描述】:

首先,我不喜欢“以 django 的方式做事”。在开发应用程序时,我更喜欢利用我的基本编程知识,而不是花费数小时学习 django 方式。 背景:

我正在开发的应用程序是一个 REST 后端,用于存储语言信息等本地化值。 我想获取存储在数据库中的语言信息,并在启动时将其加载到内存中,然后在请求到来时从内存中提供该数据。 我创建了我的模型

    class Text(models.Model):
        language = models.CharField()
        key = models.CharField()
        text = models.CharField()

然后按常规步骤运行 python manage.py makemigrations 和迁移命令 然后我跳过去,实现了我的缓存代码,直接放在admin.py下(可以是urls.py没关系,只需要运行一次)

    cached_languages = models.Text.objects.all()

我继续运行我的应用程序,它运行良好。 然后我想在我的文本模型中添加一个字段,例如

    class Text(models.Model):
        language = models.CharField()
        key = models.CharField()
        text = models.CharField()
        **dummy = models.CharField()**

然后点击 python manage.py makemigrations 命令和 boom 在 行
cached_languages = models.Text.objects.all()

我们收到一条错误消息 sqlite3.OperationalError:没有这样的列:app_text.dummy

我应该怎么做才能解决这个问题?

【问题讨论】:

【参考方案1】:

问题在于,即使您调用 python manage.py makemigrations,django 也会执行编写的每一行代码。这意味着在 django 实际反映对数据库的更改之前,它会执行整个项目,当涉及到缓存行时,它会尝试从 Text 表中获取所有行,该表还没有列 dummy 但从 django 的角度来看(在代码中)表文本有一个虚拟列,这就是它抛出错误的原因。

解决方案一种解决方法是在说 settings.py 中放置一个标志

IS_RUNNING = False

并在 manage.py 中添加以下内容

from app import settings
if 'runserver' in sys.argv:
    settings.IS_RUNNING = True

在标志检查之后放置你的缓存代码

if settings.IS_RUNNING:
     cached_languages = models.Text.objects.all()

那么 django 在应用它们之前进行迁移时不会尝试获取记录。缓存算法只会在你实际调用 runserver 时执行。

【讨论】:

希望这可以帮助那些在基本缓存方面苦苦挣扎的人 在启动时执行查询是个坏主意,这个解决方案仍然存在一些问题。创建新的Text 对象时,您的缓存已过期。当您向模型添加字段并运行 makemigrations 时会发生什么? 1) 为什么在启动时执行查询是个坏主意? 2)你可以通过启动一个守护线程来更新你的缓存,它可以每隔 300 秒更新一次你的缓存,你可以从 settings.py 或其他配置文件中读取这个值。我从来没有提到过缓存的更新。那不是重点。 3)我真的不明白你的第三句话。您首先停止服务器并运行迁移,然后启动并刷新缓存。

以上是关于Django 启动代码(如初始缓存)冲突 makemigrations。操作错误没有这样的列表的主要内容,如果未能解决你的问题,请参考以下文章

Django slugify url - 如何处理冲突?

运行 make 迁移时出现 Django 关系错误

仅在 Django 启动 ONCE 时执行代码?

redis数据库如何用Django框架缓存数据

如何避免 Python 模块系统中的命名冲突?

我如何为 django 1.8 编写初始数据