运行Django测试时遇AttributeError: 'NoneType'无rsplit属性错误求助
问题描述
在Windows 10的Docker环境中运行测试代码self.client.get("/")时,抛出AttributeError: 'NoneType' object has no attribute 'rsplit'错误。其他简单模型测试和应用本身运行正常,且该测试在另一个项目中可正常执行。
完整错误堆栈
Traceback (most recent call last): File "/usr/src/app/app/tests/test.py", line 5, in test_test resp = self.client.get("/") ^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 836, in get response = super().get(path, data=data, secure=secure, **extra) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 424, in get return self.generic( ^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 541, in generic return self.request(**r) ^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 805, in request response = self.handler(environ) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/test/client.py", line 140, in __call__ self.load_middleware() File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 61, in load_middleware mw_instance = middleware(adapted_handler) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/whitenoise/middleware.py", line 105, in __init__ self.add_files(self.static_root, prefix=self.static_prefix) File "/usr/local/lib/python3.11/site-packages/whitenoise/base.py", line 107, in add_files self.update_files_dictionary(root, prefix) File "/usr/local/lib/python3.11/site-packages/whitenoise/base.py", line 119, in update_files_dictionary self.add_file_to_dictionary(url, path, stat_cache=stat_cache) File "/usr/local/lib/python3.11/site-packages/whitenoise/base.py", line 130, in add_file_to_dictionary static_file = self.get_static_file(path, url, stat_cache=stat_cache) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/whitenoise/base.py", line 202, in get_static_file self.add_cache_headers(headers, path, url) File "/usr/local/lib/python3.11/site-packages/whitenoise/base.py", line 223, in add_cache_headers if self.immutable_file_test(path, url): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/whitenoise/middleware.py", line 177, in immutable_file_test static_url = self.get_static_url(name_without_hash) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/whitenoise/middleware.py", line 200, in get_static_url return staticfiles_storage.url(name) ^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/utils/functional.py", line 266, in inner self._setup() File "/usr/local/lib/python3.11/site-packages/django/contrib/staticfiles/storage.py", line 496, in _setup self._wrapped = get_storage_class(settings.STATICFILES_STORAGE)() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/core/files/storage.py", line 419, in get_storage_class return import_string(import_path or settings.DEFAULT_FILE_STORAGE) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/site-packages/django/utils/module_loading.py", line 25, in import_string module_path, class_name = dotted_path.rsplit(".", 1) ^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'rsplit'
测试文件
from django.test import TestCase class TestTest(TestCase): def test_test(self): resp = self.client.get("/")
docker-compose.yml(敏感数据仅用于本地开发)
version: "3.9" services: web: build: . command: python /code/manage.py runserver 0.0.0.0:8080 volumes: - .:/code ports: - 8080:8080 - 9999:9999 depends_on: - db db: image: postgres:14 environment: POSTGRES_USER: postgres POSTGRES_DB: blog POSTGRES_PASSWORD: 7895 ports: - 5432:5432 volumes: - postgres_data:/var/lib/postgresql/data/ volumes: postgres_data:
settings.py
""" Django settings for blogapp project. Generated by 'django-admin startproject' using Django 4.1.3. For more information on this file, see https://docs.djangoproject.com/en/4.1/topics/settings/ For the full list of settings and their values, see https://docs.djangoproject.com/en/4.1/ref/settings/ """ from pathlib import Path import os from dotenv import find_dotenv, load_dotenv import dj_database_url # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent load_dotenv(find_dotenv()) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! SECRET_KEY = os.getenv("SECRET_KEY") # SECURITY WARNING: don't run with debug turned on in production! DEBUG = os.getenv("DEBUG", "0").lower() in ["true", "t", "1"] ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS").split(" ") CSRF_TRUSTED_ORIGINS = os.getenv("CSRF_TRUSTED_ORIGINS").split(" ") # Application definition INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "whitenoise.runserver_nostatic", "django.contrib.staticfiles", "app.apps.AppConfig", "tinymce", "storages", ] MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ] ROOT_URLCONF = "blogapp.urls" TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [BASE_DIR.joinpath("templates")], "APP_DIRS": True, "OPTIONS": { "context_processors": [ "django.template.context_processors.debug", "django.template.context_processors.request", "django.contrib.auth.context_processors.auth", "django.contrib.messages.context_processors.messages", ], }, }, ] WSGI_APPLICATION = "blogapp.wsgi.application" # Database # https://docs.djangoproject.com/en/4.1/ref/settings/#databases DATABASES = {"default": dj_database_url.config()} # Password validation # https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, { "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] TINYMCE_JS_URL = "https://cdn.tiny.cloud/1/jys86spz5w4zp7jbfbr16eorvcw4sx1j2yg6q26namjws4do/tinymce/5/tinymce.min.js" TINYMCE_COMPRESSOR = True # Internationalization # https://docs.djangoproject.com/en/4.1/topics/i18n/ LANGUAGE_CODE = "en-us" TIME_ZONE = "UTC" USE_I18N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/4.1/howto/static-files/ STATIC_URL = "static/" MEDIA_URL = "/media/" MEDIA_ROOT = Path(BASE_DIR).joinpath("upload") STATIC_ROOT = BASE_DIR / "static/" # Default primary key field type # https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" # S3 Bucket AWS_ACCESS_KEY_ID = os.getenv("AWS_ACCESS_KEY_ID") AWS_SECRET_ACCESS_KEY = os.getenv("AWS_SECRET_ACCESS_KEY") AWS_STORAGE_BUCKET_NAME = os.getenv("AWS_STORAGE_BUCKET_NAME") DEFAULT_FILE_STORAGE = os.getenv("DEFAULT_FILE_STORAGE") AWS_S3_FILE_OVERWRITE = os.getenv("AWS_S3_FILE_OVERWRITE", "0").lower() in ["true", "t", "1"] AWS_DEFAULT_ACL = os.getenv("AWS_DEFAULT_ACL") STATICFILES_STORAGE = os.getenv("STATICFILES_STORAGE") AWS_S3_REGION_NAME = os.getenv("AWS_S3_REGION_NAME")
解决方案
错误根源是settings.py中STATICFILES_STORAGE和DEFAULT_FILE_STORAGE通过os.getenv()获取值,但本地开发环境的.env文件中未配置这两个变量,导致它们的值为None。Django尝试导入None作为存储类路径时,调用rsplit()方法就会抛出错误。
解决步骤:
- 方法一:在本地.env文件中添加默认值(使用Django内置存储类):
DEFAULT_FILE_STORAGE = django.core.files.storage.FileSystemStorage STATICFILES_STORAGE = django.contrib.staticfiles.storage.StaticFilesStorage
- 方法二:直接在
settings.py中给变量设置默认值,避免获取不到环境变量时为None:
DEFAULT_FILE_STORAGE = os.getenv("DEFAULT_FILE_STORAGE", "django.core.files.storage.FileSystemStorage") STATICFILES_STORAGE = os.getenv("STATICFILES_STORAGE", "django.contrib.staticfiles.storage.StaticFilesStorage")
生产环境需要用S3存储时,再单独配置对应存储类(比如storages.backends.s3boto3.S3Boto3Storage)即可。
内容的提问来源于stack exchange,提问作者gook
相关产品推荐
相关产品推荐

