老实说,我只是把这个开枪了,因为在问这个之前我已经尽了一切可能。我不确定这是什么问题。
我有一个Django应用程序,可以很好地在本地运行。我可以运行迁移。我在本地对此进行了详尽的开发,而在模型,测试或任何功能方面都没有一个单一的问题。
这里的问题是第二次我使用GitLab的CI / CD Runner并执行与在本地执行的完全相同的步骤,我得到了此输出。
ERRORS:
piano_gym_api.LearnerEnrolledLesson.enrolled_course: (fields.E300) Field defines a relation with model 'piano_gym_api.LearnerEnrolledCourse', which is either not installed, or is abstract.
piano_gym_api.LearnerEnrolledLesson.enrolled_course: (fields.E307) The field piano_gym_api.LearnerEnrolledLesson.enrolled_course was declared with a lazy reference to 'piano_gym_api.learnerenrolledcourse', but app 'piano_gym_api' doesn't provide model 'learnerenrolledcourse'.
piano_gym_api.LearnerEnrolledLesson.enrolled_school: (fields.E300) Field defines a relation with model 'piano_gym_api.LearnerEnrolledSchool', which is either not installed, or is abstract.
piano_gym_api.LearnerEnrolledLesson.enrolled_school: (fields.E307) The field piano_gym_api.LearnerEnrolledLesson.enrolled_school was declared with a lazy reference to 'piano_gym_api.learnerenrolledschool', but app 'piano_gym_api' doesn't provide model 'learnerenrolledschool'.
我在Django 2.2中使用Python 3.7。我的依赖项如下所示:
certifi==2019.3.9
chardet==3.0.4
coreapi==2.3.3
coreschema==0.0.4
Django==2.2
django-cors-headers==3.0.2
django-extensions==2.1.7
djangorestframework==3.9.4
djangorestframework-jwt==1.11.0
gunicorn==19.9.0
idna==2.8
itypes==1.1.0
Jinja2==2.10.1
lxml==4.3.3
MarkupSafe==1.1.1
music21==5.5.0
PyJWT==1.7.1
pytz==2019.1
requests==2.22.0
six==1.12.0
sqlparse==0.3.0
uritemplate==3.0.0
urllib3==1.25.3
whitenoise==4.1.2
我正在使用GitLab
的免费版本GitLab Runner
。
这是一个简单的Django项目。有一个项目和一个应用程序。
我的settings.conf
的INSTALLED_APPS看起来像这样
# Application definition
INSTALLED_APPS = [
# Django Default
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# Third-Party Apps
"corsheaders",
"django_extensions",
"rest_framework",
"rest_framework.authtoken",
"whitenoise.runserver_nostatic",
# Custom Apps
"piano_gym_api",
]
这将通过
pip3 install virtualenv
virtualenv -p python3 venv
source venv/bin/activate
pip3 install -r requirements.txt
python3 manage.py makemigrations piano_gym_api
python3 manage.py migrate
python3 manage.py test
这将失败
我已经安装了GitLab Runner
我在根目录中创建了一个.gitlab-ci.yml
文件。它的全部是这样:
stages:
- test
api-test:
stage: test
image: python:3.7
script:
- cd piano_gym_back_end
# Create environment for python
- pip3 install virtualenv
- virtualenv -p python3 venv
- source venv/bin/activate
- pip3 install -r requirements.txt
# Set up and run tests
- python3 manage.py makemigrations piano_gym_api
- python3 manage.py migrate
- python3 manage.py test
然后我将所有内容提交到分支并运行
gitlab-runner exec docker api-test
然后遍历所有内容并输出
$ python3 manage.py makemigrations piano_gym_api
SystemCheckError: System check identified some issues:
ERRORS:
piano_gym_api.LearnerEnrolledLesson.enrolled_course: (fields.E300) Field defines a relation with model 'piano_gym_api.LearnerEnrolledCourse', which is either not installed, or is abstract.
piano_gym_api.LearnerEnrolledLesson.enrolled_course: (fields.E307) The field piano_gym_api.LearnerEnrolledLesson.enrolled_course was declared with a lazy reference to 'piano_gym_api.learnerenrolledcourse', but app 'piano_gym_api' doesn't provide model 'learnerenrolledcourse'.
piano_gym_api.LearnerEnrolledLesson.enrolled_school: (fields.E300) Field defines a relation with model 'piano_gym_api.LearnerEnrolledSchool', which is either not installed, or is abstract.
piano_gym_api.LearnerEnrolledLesson.enrolled_school: (fields.E307) The field piano_gym_api.LearnerEnrolledLesson.enrolled_school was declared with a lazy reference to 'piano_gym_api.learnerenrolledschool', but app 'piano_gym_api' doesn't provide model 'learnerenrolledschool'.
ERROR: Job failed: exit code 1
FATAL: exit code 1
现在,我了解到这表明它无法在应用piano_gym_api
中找到模型。但这没有道理。
这里的模型是:
class LearnerEnrolledLesson(Model):
is_enrolled = BooleanField(default=True)
learner = ForeignKey("piano_gym_api.Learner", on_delete=CASCADE)
# ---
enrolled_school = ForeignKey("piano_gym_api.LearnerEnrolledSchool", on_delete=CASCADE)
enrolled_course = ForeignKey("piano_gym_api.LearnerEnrolledCourse", on_delete=CASCADE)
# ---
school = ForeignKey(School, on_delete=CASCADE)
course = ForeignKey(SchoolCourse, on_delete=CASCADE)
lesson = ForeignKey(SchoolLesson, on_delete=CASCADE)
order = IntegerField(default=1)
REQUIRED_FIELDS = ["learner", "school", "course", "lesson", "enrolled_school", "enrolled_course"]
objects = LearnerEnrolledLessonManager()
class Meta:
ordering = ("order",)
unique_together = ("learner", "school", "course", "lesson", "enrolled_school", "enrolled_course", "order")
我在这里唯一要做的就是使用字符串来引用piano_gym_api.LearnerEnrolledSchool
和piano_gym_api.LearnerEnrolledCourse
。
之所以这样做,是因为这些模型具有返回LearnerEnrolledLesson
的函数并且是循环依赖项,因此我必须引用这些模型而不使用导入路径。
我不知道为什么在我的CI / CD泊坞环境中这会失败。我没有做任何不同的事情。我的settings.py
在开发环境和ci / cd环境之间没有变化。而且,步骤完全相同。
我在这里可能做错了什么?
答案 0 :(得分:0)
我找到了解决这个问题的方法,这非常微妙。
首先,我要感谢Python Discord Channel中一个叫Mark ♦
的人。由于他们的努力与我一起坐下来,并逐步完成了我所做的工作,我们得以诊断出这一点。
这里的问题很微妙,因为在sqlite3
中没有问题。但是,当我迁移到postgresql
时出现了问题。
具体的问题是我没有这样做,所以我的模型可用。
Django要求模型存在于路径中
django_project_name/django_app_name/models.py
或
django_project_name/django_app_name/models/
我的目录结构实际上是这样的
├── requirements.txt
├── manage.py
├── django_app_name
│ ├── models
│ │ └── __init__.py
│ ├── urls.py
│ └── versions
│ ├── __init__.py
│ └── v1
│ ├── __init__.py
│ ├── models
│ │ ├── __init__.py
│ │ └── ...
│ └── views
│ ├── __init__.py
│ └── ...
└── django_project_name
└── ...
这里的问题是,为了创建版本化的目录结构,我将模型移至django_project_name/django_app_name/versions/v1/
由于这个Django无法找到模型,因为我没有通过Django应用程序中期望的models.py
文件或models
目录明确地使它们可用。
这就是为什么我会得到一个错误,即尽管存在特定模型,但Django仍然找不到。
要修复此解决方案,我必须通过将其引用导出到django_project_name/django_app_name/models/__init__.py
文件中来显式公开它们。
看起来像这样:
# REQUIRED!!!
# Django requires models that are being used to be exposed in this models
# directory
# Because we have opted to use the `versions` folder for storing the structure
# of our project, that means we need to surface those models explicitly here in
# order to remove the possibility of a missing model during the `makemigrations`
# and `migrate` commands
from django_app_name.versions.v1.models.example_model_one import *
from django_app_name.versions.v1.models.example_model_two import *
from django_app_name.versions.v1.models.example_model_three import *
...
有了这个,我就可以将我的模型用于makemigrations
和migrate
。
非常微妙:)