Pisahkan models.py menjadi beberapa file

91

Saya mencoba membagi models.pyaplikasi saya menjadi beberapa file:

Tebakan pertama saya adalah melakukan ini:

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

Ini tidak berhasil, lalu saya menemukan ini , tetapi dalam solusi ini saya masih memiliki masalah, ketika saya menjalankan python manage.py sqlall app1saya mendapat sesuatu seperti:

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;

Saya tidak begitu yakin tentang ini, tapi saya khawatir tentang bagian itu The following references should be added but depend on non-existent tables:

Ini adalah file model1.py saya:

from django.db import models

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

Ini adalah file model3.py saya:

from django.db import models

from store.models import Store

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

Dan ternyata berfungsi tetapi saya mendapat komentar alter tabledan jika saya mencoba ini, hal yang sama terjadi:

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

Jadi, haruskah saya menjalankan perubahan untuk referensi secara manual? ini mungkin membawa saya masalah dengan selatan?

diegueus9
sumber
Apa yang terjadi pada model 3 jika Anda mencoba from app1.models.model1 import Store?
James Khoury
Anda juga mungkin ingin melihat stackoverflow.com/questions/5534206/…
James Khoury

Jawaban:

33

Saya akan melakukan hal berikut:

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

Kemudian

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

Tapi, jika Anda tidak memiliki alasan yang tepat, letakkan model1 dan model2 langsung di app1 / models.py dan model3 dan model4 di app2 / models.py

---bagian kedua---

Ini adalah file app1 / submodels / model1.py:

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

Jadi perbaiki file model3.py Anda:

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

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

Diedit, jika ini muncul lagi untuk seseorang: Lihat django-schedule untuk contoh proyek yang melakukan hal ini. https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/

Ted
sumber
1
Sehubungan dengan jawaban ini saya mendapat masalah lain ketika di models2.py membuat sesuatu seperti from product.models import Product: ImportError: No module bernama models
diegueus9
68
Anda akan melakukannya dengan cara ini untuk mempertahankan satu kelas per file.
worc
50
"Mengapa" adalah keinginan untuk mengurangi ukuran models.pyfile yang sangat besar . Saya baru-baru ini melakukan ini ketika milik saya berkembang menjadi lebih dari 15k baris kode. Tulisan yang bagus sekalipun. Prosesnya cukup sederhana. Peringatan utamanya adalah anda harus ingat untuk mendefinisikan label_aplikasi eksplisit, karena Django mengekstrak ini dari modul langsung secara baku.
Cerin
1
Mencoba ini pada 2016. Apakah bagian kedua dari posting ini masih diperlukan? Saya hanya memindahkan kelas ke file terpisah, menulis saya __init__.pydan semuanya tampak berfungsi dengan baik. Saya tidak perlu mengoreksi file model saya. Saya dapat mengambil dan membuat objek dari shell dan admin django. Saya sudah mencoba Django selama seminggu jadi saya bertanya-tanya apakah versi terbaru sekarang memungkinkan hal ini terjadi?
Vic
3
@Vic: App_label di kelas Meta tidak lagi diperlukan dengan versi terbaru dari Django. Lihat code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial
149

Untuk siapa saja di Django 1.9, sekarang didukung oleh kerangka kerja tanpa mendefinisikan meta data kelas.

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

CATATAN: Untuk Django 2, itu masih sama

Itu manage.py startapp Perintah menciptakan struktur aplikasi yang berisi file models.py. Jika Anda memiliki banyak model, mengaturnya dalam file terpisah mungkin berguna.

Untuk melakukannya, buat paket model. Hapus models.py dan buat myapp/models/direktori dengan __init__.pyfile dan file untuk menyimpan model Anda. Anda harus mengimpor model di __init__.pyfile.

Jadi, dalam kasus Anda, untuk struktur seperti

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

Anda hanya perlu melakukannya

#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

Catatan terhadap mengimpor semua kelas:

Mengimpor setiap model secara eksplisit daripada menggunakan from .models import *memiliki keuntungan karena tidak mengacaukan namespace, membuat kode lebih mudah dibaca, dan menjaga alat analisis kode tetap berguna.

Vic
sumber
6
Dalam kasus seseorang bertanya-tanya apakah itu masih up to date dengan Django 2.0 docs.djangoproject.com/en/2.0/topics/db/models/...
NaturalBornCamper
7
CATATAN: Ini biasanya tidak berfungsi dengan baik ketika Anda telah memulainya models.pydan ingin bermigrasi nanti. Dalam hal ini, Anda harus menghapus migrasi dan database Anda: / Atau untuk secara manual menyelesaikan semua kesalahan di semua file migrasi
tuergeist
Jawaban terbaik masih. Dapat mengonfirmasi ini masih berfungsi di 2.1+
Roys
1
Saya tidak melihat masalah yang ditunjukkan oleh @tuergeist di Django 3.0. Tampaknya bekerja seperti pesona
karam
11

Saya benar-benar menemukan tutorial tentang apa yang Anda tanyakan, Anda dapat melihatnya di sini:

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

Satu poin kunci yang mungkin relevan - Anda mungkin ingin menggunakan bidang db_table di kelas Meta untuk mengarahkan kembali kelas yang direlokasi ke tabel mereka sendiri.

Saya dapat mengkonfirmasi pendekatan ini bekerja di Django 1.3

Adam Luchjenbroers
sumber
Tautan itu memberikan 404
Bryan Oakley
1

Langkah termudah:

  1. Buat folder model di aplikasi Anda (Nama folder harus model )
  2. Hapus file model.py dari direktori aplikasi (Cadangkan file saat Anda menghapusnya)
  3. Dan setelah membuat init file .py di folder model
  4. Dan setelah init file .py di tulis sederhana satu baris
  5. Dan setelah membuat file model di folder model Anda dan nama file model harus sama seperti nama kelas, jika nama kelas adalah 'Employee' maka nama file model harus seperti 'employee.py'
  6. Dan setelah di file model tentukan tabel database Anda sama seperti tulis seperti di file model.py
  7. Simpan itu

Kode Saya: dari django_adminlte.models.employee import Employee

Untuk Anda: dari 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
Parth Jani
sumber
2
Inilah tepatnya yang dia coba perbaiki. Solusi ini akan menyebabkan RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.di django 2.x.
radtek
0

Saya menulis naskah yang mungkin berguna.

github.com/victorqribeiro/splitDjangoModels

itu membagi model dalam file individual dengan penamaan dan impor yang tepat; itu juga membuat file init sehingga Anda dapat mengimpor semua model Anda sekaligus.

beri tahu saya jika ini membantu

pengguna1659565
sumber