Chia models.py thành nhiều tệp


89

Tôi đang cố gắng chia models.pyứng dụng của mình thành nhiều tệp:

Dự đoán đầu tiên của tôi là làm điều này:

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

Điều này không hoạt động, sau đó tôi tìm thấy điều này , nhưng trong giải pháp này, tôi vẫn gặp sự cố, khi tôi chạy, python manage.py sqlall app1tôi nhận được một cái gì đó như:

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;

Tôi không chắc về điều này, nhưng tôi lo lắng về phần The following references should be added but depend on non-existent tables:

Đây là tệp model1.py của tôi:

from django.db import models

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

Đây là tệp model3.py của tôi:

from django.db import models

from store.models import Store

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

Và dường như hoạt động nhưng tôi đã nhận xét alter tablevà nếu tôi thử điều này, điều tương tự sẽ xảy ra:

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

Vì vậy, tôi có nên chạy thay đổi cho các tham chiếu theo cách thủ công không? điều này có thể mang lại cho tôi vấn đề với phía nam?


Điều gì xảy ra trong mô hình 3 nếu bạn thử from app1.models.model1 import Store?
James Khoury

Ngoài ra bạn có thể muốn kiểm tra stackoverflow.com/questions/5534206/...
James Khoury

Câu trả lời:


32

Tôi sẽ làm như sau:

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

Sau đó

#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 *

Tuy nhiên, nếu bạn không có lý do chính đáng, hãy đặt model1 và model2 trực tiếp vào app1 / models.py và model3 và model4 trong app2 / models.py

--- phần thứ hai ---

Đây là tệp app1 / submodels / model1.py:

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

Do đó, hãy sửa tệp model3.py của bạn:

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

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

Đã chỉnh sửa, trong trường hợp điều này xuất hiện lại cho ai đó: Hãy xem lịch trình django để biết ví dụ về một dự án thực hiện điều này. https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/


1
Đối với câu trả lời này với tôi đã nhận một vấn đề khác khi trong models2.py làm một cái gì đó như from product.models import Product: ImportError: Không có mô-đun tên mô hình
diegueus9

68
bạn sẽ làm theo cách này để duy trì một lớp cho mỗi tệp.
worc

50
"Tại sao" sẽ là mong muốn giảm kích thước của một models.pytệp lớn . Gần đây tôi đã làm điều này khi tôi đã tăng lên hơn 15 nghìn dòng mã. Viết tốt mặc dù. Quá trình này khá đơn giản. Cảnh báo chính mà bạn phải nhớ là xác định một app_label rõ ràng, vì Django trích xuất mã này từ mô-đun ngay lập tức theo mặc định.
Cerin

1
Hãy thử phần này vào năm 2016. Bạn vẫn cần phần thứ hai của bài đăng này chứ? Tôi chỉ di chuyển các lớp sang các tệp riêng biệt, viết của tôi __init__.pyvà mọi thứ dường như hoạt động ổn. Tôi không phải sửa các tệp mô hình của mình. Tôi có thể tìm nạp và tạo các đối tượng từ shell và quản trị viên django. Tôi đã thử django được một tuần nên tôi tự hỏi liệu phiên bản mới nhất hiện nay có cho phép điều này xảy ra không?
Vic

3
@Vic: App_label trong lớp Meta không còn cần thiết với các phiên bản mới hơn của Django. Xem code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial

147

Đối với bất kỳ ai trên Django 1.9, nó hiện được hỗ trợ bởi khuôn khổ mà không cần xác định dữ liệu meta lớp.

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

LƯU Ý: Đối với Django 2, nó vẫn như cũ

Các manage.py startapplệnh tạo ra một cấu trúc ứng dụng bao gồm một tập tin models.py. Nếu bạn có nhiều mô hình, tổ chức chúng thành các tệp riêng biệt có thể hữu ích.

Để làm như vậy, hãy tạo một gói mô hình. Loại bỏ models.py và tạo một myapp/models/thư mục với một __init__.pytệp và các tệp để lưu trữ các mô hình của bạn. Bạn phải nhập các mô hình trong __init__.pytệp.

Vì vậy, trong trường hợp của bạn, đối với một cấu trúc như

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

Bạn chỉ cần làm

#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

Lưu ý chống lại việc nhập tất cả các lớp:

Việc nhập rõ ràng từng mô hình thay vì sử dụng from .models import *có những ưu điểm là không làm lộn xộn vùng tên, làm cho mã dễ đọc hơn và giữ cho các công cụ phân tích mã hữu ích.


5
Trong trường hợp ai đó đang tự hỏi nếu nó vẫn còn đến ngày với Django 2,0 docs.djangoproject.com/en/2.0/topics/db/models/...
NaturalBornCamper

6
LƯU Ý: Điều này thường không hoạt động đúng khi bạn đã bắt đầu models.pyvà muốn di chuyển sau. Trong trường hợp đó, bạn phải xóa di cư của bạn và cơ sở dữ liệu của bạn: / Hoặc tự giải quyết tất cả các lỗi trong tất cả các file chuyển
tuergeist

Câu trả lời tốt nhất vẫn còn. Có thể xác nhận điều này vẫn hoạt động trong 2.1+
Roys

Tôi không thấy vấn đề được @tuergeist chỉ ra trong Django 3.0. Có vẻ hoạt động như một sự quyến rũ
caram

11

Tôi thực sự đã xem qua một hướng dẫn cho chính xác những gì bạn đang hỏi, bạn có thể xem nó tại đây:

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

Một điểm chính có lẽ có liên quan - bạn có thể muốn sử dụng trường db_table trên lớp Meta để trỏ các lớp được chuyển vị trí trở lại bảng của chính chúng.

Tôi có thể xác nhận phương pháp này đang hoạt động trong Django 1.3


Liên kết cung cấp cho 404
Bryan Oakley

1

Các bước dễ nhất:

  1. Tạo thư mục mô hình trong ứng dụng của bạn (Tên thư mục phải là mô hình )
  2. Xóa tệp model.py khỏi thư mục ứng dụng (Sao lưu tệp trong khi bạn xóa nó)
  3. Và sau khi tạo tệp init .py trong thư mục mô hình
  4. Và sau khi init tệp .py trong ghi một dòng đơn giản
  5. Và sau khi tạo tệp mô hình trong thư mục mô hình của bạn và tên tệp mô hình phải giống như tên lớp, nếu tên lớp là 'Nhân viên' thì tên tệp mô hình phải giống như 'worker.py'
  6. Và sau khi trong tệp mô hình, xác định bảng cơ sở dữ liệu của bạn giống như ghi như trong tệp model.py
  7. Lưu nó

Mã của tôi: từ django_adminlte.models.employee nhập Nhân viên

Đối với của bạn: from app_name .models. model_file_name_only nhập khẩu 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
Đây chính là điều anh ấy đang cố gắng sửa chữa. Giải pháp này sẽ gây ra RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.trong django 2.x.
radtek

0

Tôi đã viết một kịch bản có thể hữu ích.

github.com/victorqribeiro/splitDjangoModels

nó phân chia các mô hình trong các tệp riêng lẻ với cách đặt tên và nhập phù hợp; nó cũng tạo một tệp init để bạn có thể nhập tất cả các mô hình của mình cùng một lúc.

Hãy cho tôi biết nếu điều này sẽ giúp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.