models.py를 여러 파일로 분할


89

models.py내 앱을 여러 파일로 분할하려고 합니다.

내 첫 번째 추측은 다음과 같습니다.

myproject/
    settings.py
    manage.py
    urls.py
    __init__.py
    app1/
        views.py
        __init__.py
        models/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models/
            __init__.py
            model3.py
            model4.py

이것은 작동하지 않는 다음 이것을 찾았 지만이 솔루션에서는 여전히 문제가 있습니다. 실행하면 python manage.py sqlall app1다음과 같은 결과가 나타납니다.

BEGIN;
CREATE TABLE "product_product" (
    "id" serial NOT NULL PRIMARY KEY,
    "store_id" integer NOT NULL
)
;
-- The following references should be added but depend on non-existent tables:
-- ALTER TABLE "product_product" ADD CONSTRAINT "store_id_refs_id_3e117eef" FOREIGN KEY     ("store_id") REFERENCES "store_store" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "product_product_store_id" ON "product_product" ("store_id");
COMMIT;

나는 이것에 대해 잘 모르겠지만 부분이 걱정됩니다. The following references should be added but depend on non-existent tables:

이것은 내 model1.py 파일입니다.

from django.db import models

class Store(models.Model):
    class Meta:
        app_label = "store"

이것은 내 model3.py 파일입니다.

from django.db import models

from store.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

그리고 분명히 작동하지만 코멘트를 alter table받았으며 이것을 시도하면 똑같은 일이 발생합니다.

class Product(models.Model):
    store = models.ForeignKey('store.Store')
    class Meta:
        app_label = "product"

그렇다면 참조를 위해 변경을 수동으로 실행해야합니까? 이것은 나에게 남쪽 문제를 가져올 수 있습니까?


시도하면 모델 3에서 어떤 일이 발생 from app1.models.model1 import Store합니까?
James Khoury 2011 년

답변:


33

다음을 수행합니다.

myproject/
    ...
    app1/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model1.py
            model2.py
    app2/
        views.py
        __init__.py
        models.py
        submodels/
            __init__.py
            model3.py
            model4.py

그때

#myproject/app1/models.py:
    from submodels/model1.py import *
    from submodels/model2.py import *

#myproject/app2/models.py:
    from submodels/model3.py import *
    from submodels/model4.py import *

그러나 정당한 이유가 없다면 model1과 model2를 app1 / models.py에 직접 넣고 model3과 model4를 app2 / models.py에 넣으십시오.

--- 두 번째 부분 ---

이것은 app1 / submodels / model1.py 파일입니다.

from django.db import models
class Store(models.Model):
    class Meta:
        app_label = "store"

따라서 model3.py 파일을 수정하십시오.

from django.db import models
from app1.models import Store

class Product(models.Model):
    store = models.ForeignKey(Store)
    class Meta:
        app_label = "product"

누군가를 위해 이것이 다시 나올 경우를 대비하여 편집 됨 :이 작업을 수행하는 프로젝트의 예는 django-schedule을 확인하십시오. https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/


1
이 답변과 관련하여 models2.py에서 다음과 같이 만들 때 또 다른 문제가 발생했습니다 from product.models import Product. ImportError : No module named models
diegueus9

68
이 방법으로 파일 당 하나의 클래스를 유지합니다.
worc

50
"이유"는 대용량 models.py파일 의 크기를 줄이려는 욕구 입니다. 나는 최근에 15k 라인 이상의 코드로 성장했을 때 이것을했습니다. 그래도 훌륭한 글. 과정은 매우 간단합니다. Django는 기본적으로 직접 모듈에서이를 추출하기 때문에 명시적인 app_label을 정의하는 것을 기억해야합니다.
Cerin

1
2016 년에 시도해보세요.이 게시물의 두 번째 부분이 여전히 필요합니까? 나는 수업을 별도의 파일로 옮겼고, 내 글을 썼고 __init__.py모든 것이 잘 작동하는 것 같습니다. 모델 파일을 수정할 필요가 없었습니다. 셸과 장고 관리자에서 개체를 가져오고 만들 수 있습니다. 나는 일주일 동안 django를 시도해 왔기 때문에 최신 버전이 이것이 일어나도록 허용하는지 궁금합니다.
Vic은

3
@Vic : Meta 클래스의 app_label은 최신 버전의 Django에서 더 이상 필요하지 않습니다. 참조 code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial

147

Django 1.9의 모든 사용자는 이제 클래스 메타 데이터를 정의하지 않고 프레임 워크에서 지원합니다.

https://docs.djangoproject.com/en/1.9/topics/db/models/#organizing-models-in-a-package

참고 : Django 2 의 경우 여전히 동일합니다.

manage.py startapp명령은 models.py 파일을 포함하는 애플리케이션 구조를 생성합니다. 모델이 많은 경우 별도의 파일로 구성하는 것이 유용 할 수 있습니다.

이렇게하려면 모델 패키지를 만듭니다. models.py를 제거하고 모델을 저장할 파일과 파일이 있는 myapp/models/디렉토리를 만듭니다 __init__.py. __init__.py파일 의 모델을 가져와야 합니다.

따라서 귀하의 경우에는

app1/
    views.py
    __init__.py
    models/
        __init__.py
        model1.py
        model2.py
app2/
    views.py
    __init__.py
    models/
        __init__.py
        model3.py
        model4.py

당신은 할 필요가 있습니다

#myproject/app1/models/__init__.py:
from .model1 import Model1
from .model2 import Model2

#myproject/app2/models/__init__.py:
from .model3 import Model3
from .model4 import Model4

모든 클래스 가져 오기에 대한 참고 사항 :

사용하지 않고 각 모델을 명시 적으로 가져 오면 from .models import *네임 스페이스를 복잡하게 만들지 않고 코드를 더 쉽게 읽을 수 있으며 코드 분석 도구를 유용하게 유지할 수 있다는 장점이 있습니다.


5
이 장고 최신 상태로 여전히 2.0의 경우 경우 누군가가 궁금해 docs.djangoproject.com/en/2.0/topics/db/models/...
NaturalBornCamper

6
참고 : 일반적으로을 (를) 시작하고 models.py나중에 마이그레이션하려는 경우 제대로 작동하지 않습니다 . 이 경우, 당신은 당신의 마이그레이션 및 데이터베이스를 삭제해야합니다 : / 또는 수동으로 모든 마이그레이션 파일의 모든 오류 해결
tuergeist

여전히 최고의 답변입니다. 2.1+에서도 여전히 작동하는지 확인할 수 있습니다.
Roys

Django 3.0에서 @tuergeist가 지적한 문제가 보이지 않습니다. 매력처럼 작동하는 것 같습니다
caram

11

실제로 질문하는 내용에 대한 자습서를 보았습니다. 여기에서 볼 수 있습니다.

http://paltman.com/breaking-apart-models-in-django/

관련이있을 수있는 한 가지 요점은 Meta 클래스의 db_table 필드를 사용하여 재배치 된 클래스가 자신의 테이블을 다시 가리 키도록 할 수 있습니다.

이 접근 방식이 Django 1.3에서 작동하는지 확인할 수 있습니다.


그 링크는 404를 제공합니다
Bryan Oakley

1

가장 쉬운 단계 :

  1. 앱에 모델 폴더 생성 (폴더 이름은 model 이어야 함 )
  2. 앱 디렉토리에서 model.py 파일 삭제 (파일을 삭제하는 동안 백업)
  3. 그리고 모델 폴더에 init .py 파일을 만든 후
  4. 그리고 init .py 파일을 간단한 한 줄로 작성하십시오.
  5. 그리고 모델 폴더에 모델 파일을 생성 한 후 모델 파일 이름은 클래스 이름과 같아야 합니다. 클래스 이름이 'Employee'이면 모델 파일 이름은 'employee.py'와 같아야합니다.
  6. 그리고 모델 파일에서 model.py 파일 과 같은 쓰기와 동일한 데이터베이스 테이블을 정의하십시오.
  7. 저장해

내 코드 : django_adminlte.models.employee import Employee

귀하의 : app_name .models에서. model_file_name_only import Class_Name_which_define_in_model_file


__init__.py

from django_adminlte.models.employee import Employee

model/employee.py (employee is separate model file)

from django.db import models

class Employee(models.Model):
eid = models.CharField(max_length=20)
ename = models.CharField(max_length=20)
eemail = models.EmailField()
econtact = models.CharField(max_length=15)

class Meta:
    db_table = "employee"
    # app_label = 'django_adminlte'
    
def __str__(self):
    return self.ename

2
이것이 바로 그가 고치려는 것입니다. 이 솔루션은 RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.django 2.x에서 발생합니다 .
radtek

0

유용한 스크립트를 작성했습니다.

github.com/victorqribeiro/splitDjangoModels

적절한 이름 지정 및 가져 오기를 통해 모델을 개별 파일로 분할합니다. 또한 한 번에 모든 모델을 가져올 수 있도록 init 파일을 생성합니다.

도움이되는지 알려주세요

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.