django 在www.example.com测试迁移之前,AppConfig.ready()正在运行manage.py

osh3o9ms  于 2023-03-31  发布在  Go
关注(0)|答案(1)|浏览(134)

我正在尝试使用Django的AppConfig.ready()方法在其中一个模型上运行一些查询来检索一些数据。
下面的代码:

class NewsConfig(AppConfig):
    name = "apps.news"
    verbose_name = "News"

    def ready(self):
        NewsType = self.models.get("newstype")
        NewsType.names = NewsType.objects.values_list("name", flat=True)

然后,在urls.py上,我使用它们如下:

news_type_names_regex = generate_regex(NewsType.names)

router = DefaultRouter()
router.register(r'news/' + news_type_names_regex, NewsModelViewSet, basename='news')

当应用程序运行时(使用uvicorn或runserver),这工作正常,但当运行测试时,AppConfig.ready()在迁移运行之前被执行,这导致以下错误:

...
django.db.utils.OperationalError: no such table: news_newstype

我已经阅读了文档中的警告,但我不认为它与这个问题有关。我在AppConfig.ready()上这样做的原因是因为它需要在django.setup()之后的某个地方完成,而不是在异步请求上下文中(因为我正在使用django通道并运行应用程序ASGI)。

shyt4zoc

shyt4zoc1#

解释

这在应用程序运行时(使用uvicorn或runserver)工作正常,但在运行测试时,AppConfig.ready()会在迁移运行之前执行。
这是完全正确的,服务器运行正常的原因是news_newstype表已经存在,因为创建该表的迁移已经应用。
但是,在运行测试时,迁移会在运行测试之前运行,并且由于测试数据库中尚未创建表news_newstype,因此会导致错误。
溶液
您应该删除从数据库值生成的动态URL路径,并避免代码引用NewsConfig.ready()中的数据库表。
相反,您可以使用URL参数捕获,并使用捕获的值在视图方法中搜索数据库。
urls.py

from django.urls import path

urlpatterns = [
    path("news/<news_type>/", NewsView.as_view()),
]

然后在视图方法中使用捕获的news_type参数

from django.shortcuts import get_object_or_404
from rest_framework import generics

class NewsView(generics.GenericAPIView)
    def get(self, request, news_type=None):
        # equivalent to NewsType.objects.get(name=news_type)
        # and return response with HTTP 404 status when it's not found
        get_object_or_404(NewType, name=news_type)
        # your code goes here
        ...

注解

这只是一个generics.GenericAPIView的例子,如果你想使用viewset,请阅读restframework文档。
另外,你可以在django文档中找到关于URL参数捕获的文档。

相关问题