Models.py'yi birkaç dosyaya bölün


91

models.pyUygulamamı birkaç dosyaya bölmeye çalışıyorum :

İlk tahminim şunu yapmaktı:

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

Bu işe yaramıyor, sonra bunu buldum , ancak bu çözümde hala bir sorun var, çalıştırdığımda python manage.py sqlall app1şöyle bir şey var:

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;

Bundan pek emin değilim ama bu kısım için endişeliyim The following references should be added but depend on non-existent tables:

Bu benim model1.py dosyam:

from django.db import models

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

Bu benim model3.py dosyam:

from django.db import models

from store.models import Store

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

Ve görünüşe göre çalışıyor ama yorumu aldım alter tableve bunu denersem aynı şey olur:

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

Öyleyse, referanslar için değişikliği manuel olarak çalıştırmalı mıyım? bu bana güneyle ilgili sorunlar getirebilir mi?


Denerseniz model 3'te ne olur from app1.models.model1 import Store?
James Khoury

Yanıtlar:


33

Aşağıdakileri yapardım:

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

Sonra

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

Ancak, iyi bir nedeniniz yoksa model1 ve model2'yi doğrudan app1 / models.py'ye ve model3 ve model4'ü app2 / models.py içine koyun.

---ikinci kısım---

Bu app1 / submodels / model1.py dosyasıdır:

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

Bu nedenle model3.py dosyanızı düzeltin:

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

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

Birisi için bu tekrar ortaya çıkarsa diye düzenlendi: Sadece bunu yapan bir proje örneği için django-programına bakın. https://github.com/thauber/django-schedule/tree/master/schedule/models https://github.com/thauber/django-schedule/


1
Bu yanıtla ilgili olarak, models2.py'de şöyle bir şey yaptığımda başka bir sorunla karşılaştım from product.models import Product: ImportError: Model adında modül yok
diegueus9

68
dosya başına bir sınıf tutmak için bu şekilde yaparsınız.
worc

50
"Neden", büyük bir models.pydosyanın boyutunu küçültme arzusudur . Bunu geçenlerde benimki 15.000 satır koda ulaştığında yaptım. Yine de harika bir yazı. İşlem oldukça basit. Ana uyarı, Django bunu varsayılan olarak anlık modülden çıkardığından, açık bir app_label tanımlamayı hatırlamanız gerektiğidir.
Cerin

1
2016'da bunu denemek. Bu yazının ikinci kısmına hala ihtiyaç var mı? Sınıfları yalnızca ayrı dosyalara taşıdım, yazdım __init__.pyve her şey yolunda görünüyor. Model dosyalarımı düzeltmek zorunda değildim. Kabuktan ve django yöneticisinden nesneler getirip oluşturabiliyorum. Django'yu bir haftadır deniyorum, bu yüzden en yeni sürümün buna izin verip vermediğini merak ediyorum.
Vic

3
@Vic: Meta sınıfındaki app_label artık Django'nun daha yeni sürümlerinde gerekli değildir. Bkz. Code.djangoproject.com/wiki/CookBookSplitModelsToFiles
jrial

149

Django 1.9'daki herkes için, artık sınıf meta verilerini tanımlamadan çerçeve tarafından destekleniyor.

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

NOT: Django 2 için hala aynı

manage.py startappKomutu bir models.py dosyasını içeren bir uygulama yapısını oluşturur. Çok sayıda modeliniz varsa, bunları ayrı dosyalarda düzenlemek faydalı olabilir.

Bunu yapmak için bir model paketi oluşturun. Models.py dosyasını kaldırın ve myapp/models/bir __init__.pydosya ve modellerinizi depolamak için dosyalar içeren bir dizin oluşturun . Modelleri __init__.pydosyaya aktarmalısınız .

Yani, sizin durumunuzda, aşağıdaki gibi bir yapı için

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

Sadece yapman gerekiyor

#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

Tüm sınıfların içe aktarılmasına karşı bir not:

Her modeli kullanmak yerine açıkça içe aktarmak from .models import *, ad alanını karıştırmamak, kodu daha okunaklı hale getirmek ve kod analiz araçlarını kullanışlı tutmak gibi avantajlara sahiptir.


6
Birinin Django 2.0 docs
NaturalBornCamper

7
NOT: Bu, başladığınızda models.pyve daha sonra taşımak istediğinizde genellikle düzgün çalışmaz . Bu durumda, taşıma işlemlerinizi ve veritabanınızı silmeniz gerekir: / Veya tüm taşıma dosyalarındaki tüm hataları manuel olarak çözmek için
öğretmen

Hala en iyi cevap. 2.1+ bu hala çalışmalarını teyit edebilir
Roys

1
Django 3.0'da @ tuergeist tarafından belirtilen sorunu görmüyorum. Bir cazibe gibi çalışıyor
caram

11

Aslında tam olarak ne sorduğunuza dair bir öğretici ile karşılaştım, buradan görüntüleyebilirsiniz:

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

Muhtemelen alakalı olan bir anahtar nokta - taşınan sınıfları kendi tablolarına geri götürmek için Meta sınıfındaki db_table alanını kullanmak isteyebilirsiniz.

Bu yaklaşımın Django 1.3'te çalıştığını doğrulayabilirim


Bu bağlantı 404 veriyor
Bryan Oakley

1

En Kolay Adımlar:

  1. Uygulamanızda model klasörü oluşturun (Klasör adı model olmalıdır )
  2. Model.py dosyasını uygulama dizininden silin (Dosyayı silerken yedekleyin)
  3. Ve yarattıktan sonra model klasöründe init .py dosyası
  4. Ve sonra init .py dosyasından basit bir satır yazın
  5. Ve model klasörünüzde model dosyası oluşturduktan sonra ve model dosya adı, sınıf adı ile aynı olmalıdır, eğer sınıf adı 'Çalışan' ise, model dosya adı 'employee.py' şeklinde olmalıdır.
  6. Ve model dosyasından sonra veritabanı tablonuzu yazarken olduğu gibi tanımlayın model.py dosyasındaki
  7. Onu kurtar

Kodum: django_adminlte.models.employee import Employee'den

Sizin için: app_name .models'ten. model_file_name_only Class_Name_which_define_in_model_file dosyasını içe aktarın


__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
Bu tam olarak düzeltmeye çalıştığı şey. Bu çözüm RuntimeError ModelX doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.django 2.x'de neden olacaktır .
radtek

0

Yararlı olabilecek bir senaryo yazdım.

github.com/victorqribeiro/splitDjangoModels

modelleri uygun adlandırma ve içe aktarmayla ayrı dosyalara böler; aynı zamanda tüm modellerinizi bir kerede içe aktarabilmeniz için bir başlangıç ​​dosyası oluşturur.

yardımcı olursa haberim olsun

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.