2011-11-07 42 views
5

Tôi hiểu cách chia nhỏ mô hình và tôi hiểu lý do phụ thuộc vào mô-đun vòng tròn làm tăng mọi thứ, nhưng tôi đã gặp phải sự cố khi chia nhỏ mô hình thành các tệp riêng biệt dường như gây ra phụ thuộc vòng tròn. Dưới đây là một exerpt từ mã, và tôi sẽ làm theo nó với traceback từ quá trình thất bại:Phụ thuộc mô-đun tròn trong Python/Django với các mô hình chia tách

elearning/tasks.py

from celery.task import task 

@task 
def decompress(pk): 
    from elearning.models import Elearning 
    Elearning.objects.get(pk=pk).decompress() 

elearning/models.py

from competency.models import CompetencyProduct 
from core.helpers import ugc_elearning 
from elearning.fields import ArchiveFileField 

class Elearning(CompetencyProduct): 

    archive = ArchiveFileField(upload_to=ugc_elearning) 

    def decompress(self): 

     import zipfile 

     src = self.archive.path 
     dst = src.replace(".zip","") 

     print "Decompressing %s to %s" % (src, dst) 

     zipfile.ZipFile(src).extractall(dst) 

ecom/models/products.py

from django.db import models 
from django.utils.translation import ugettext_lazy as _ 

from core.models import Slugable, Unique 
from django_factory.models import Factory 
from core.helpers import ugc_photos 

class Product(Slugable, Unique, Factory): 

    photo   = models.ImageField(upload_to=ugc_photos, width_field="photo_width", height_field="photo_height", blank=True) 
    photo_width = models.PositiveIntegerField(blank=True, null=True, default=0) 
    photo_height = models.PositiveIntegerField(blank=True, null=True, default=0) 
    description = models.TextField() 
    price   = models.DecimalField(max_digits=16, decimal_places=2) 
    created  = models.DateTimeField(auto_now_add=True) 
    modified  = models.DateTimeField(auto_now=True) 

ecom/models/__init__.py

from django.contrib.auth.models import User 
from django.db import models 

from ecom.models.products import Product, Credit, Subscription 
from ecom.models.permissions import Permission 
from ecom.models.transactions import Transaction, DebitTransaction, CreditTransaction, AwardTransaction, FinancialTransaction, PermissionTransaction, BundleTransaction 

competency/models.py

from django.db import models 
from django.utils.translation import ugettext_lazy as _ 

from core.models import Slugable, Unique 
from ecom.models import Product 
from rating.models import Rated 
from trainer.models import Trainer 

class Competency(Slugable, Unique): 

    class Meta: 
     verbose_name = _("Competency") 
     verbose_name_plural = _("Competencies") 

    description = models.TextField() 



class CompetencyProduct(Product, Rated): 

    class Meta: 
     verbose_name = _("Product") 
     verbose_name_plural = _("Products") 

    release = models.DateField(auto_now_add=True) 

    trainers  = models.ManyToManyField(Trainer) 
    competencies = models.ManyToManyField(Competency, related_name="provided_by") 
    requirements = models.ManyToManyField(Competency, related_name="required_for", blank=True, null=True) 
    forsale  = models.BooleanField("For Sale", default=True) 

ecom/models/permissions.py

from django.contrib.auth.models import User 
from django.db import models 
from django.utils.translation import ugettext_lazy as _ 

from treebeard.mp_tree import MP_Node 

from collective.models import Collective 
from course.models import Course 
from ecom.models.products import Product 

class Permission(MP_Node): 

    class Meta: 
     app_label = "ecom" 

    product  = models.ForeignKey(Product, related_name="permissions") 
    user   = models.ForeignKey(User, related_name="permissions") 
    collective = models.ForeignKey(Collective, null=True) 
    course  = models.ForeignKey(Course, null=True) 
    redistribute = models.BooleanField(default=False) 
    created  = models.DateTimeField(auto_now_add=True) 
    modified  = models.DateTimeField(auto_now=True) 
    accessed  = models.DateTimeField(auto_now=True) 

course/models.py

from django.db import models 
from django.utils.translation import ugettext_lazy as _ 

from competency.models import CompetencyProduct 
from ecom.models import Product 
from rating.models import Rated 

class Chapter(models.Model): 
    seq = models.PositiveIntegerField(name="Sequence", help_text="Chapter number") 
    name = models.CharField(max_length=128) 
    note = models.CharField(max_length=128) 



class Course(Product, Rated): 

    level = models.PositiveIntegerField(choices=CompetencyProduct.LEVELS) 
    chapters = models.ManyToManyField(Chapter) 



class Bundle(models.Model): 

    class Meta: 
     unique_together = (("product", "chapter"),) 

    product = models.ForeignKey(Product, related_name="bundles") 
    chapter = models.ForeignKey(Chapter, related_name="bundles") 
    amount = models.PositiveIntegerField() 
    seq  = models.PositiveIntegerField(name="Sequence", default=1) 

Từ những gì tôi có thể thấy, không có đệ quy tròn rõ ràng ông lại, lưu các tài liệu tham khảo cần thiết trong __init__.py mà dường như là nơi mọi thứ được thổi lên trong mã của tôi. Dưới đây là traceback:

File "/path/to/project/virtualenv/lib/python2.6/site-packages/celery/execute/trace.py", line 47, in trace 
    return cls(states.SUCCESS, retval=fun(*args, **kwargs)) 
    File "/path/to/project/virtualenv/lib/python2.6/site-packages/celery/app/task/__init__.py", line 247, in __call__ 
    return self.run(*args, **kwargs) 
    File "/path/to/project/virtualenv/lib/python2.6/site-packages/celery/app/__init__.py", line 175, in run 
    return fun(*args, **kwargs) 
    File "/path/to/project/django/myproj/elearning/tasks.py", line 5, in decompress 
    from elearning.models import Elearning 
    File "/path/to/project/django/myproj/elearning/models.py", line 2, in <module> 
    from competency.models import CompetencyProduct 
    File "/path/to/project/django/myproj/competency/models.py", line 5, in <module> 
    from ecom.models import Product 
    File "/path/to/project/django/myproj/ecom/models/__init__.py", line 5, in <module> 
    from ecom.models.permissions import Permission 
    File "/path/to/project/django/myproj/ecom/models/permissions.py", line 8, in <module> 
    from course.models import Course 
    File "/path/to/project/django/myproj/course/models.py", line 4, in <module> 
    from competency.models import CompetencyProduct 
ImportError: cannot import name CompetencyProduct 

Tất cả tôi đang cố gắng để làm ở đây là nhập khẩu mà Elearning mô hình, mà là một lớp con của CompetencyProduct, và đến lượt nó, Product. Tuy nhiên, vì Product xuất phát từ sự bùng nổ của ecom/models.py lớn hơn, tệp ecom/__init__.py chứa nhập khẩu bắt buộc của tất cả các mô hình bị hỏng, bao gồm Permission phải nhập Course yêu cầu CompetencyProduct.

Điều kỳ quặc là toàn bộ trang web hoạt động tốt. Đăng nhập, mua hàng, mọi thứ. Vấn đề này chỉ xảy ra khi tôi đang cố gắng chạy cần tây trong nền và một nhiệm vụ mới được tải hoặc tôi cố gắng chạy một kịch bản shell bằng cách sử dụng môi trường Django.

Là lựa chọn duy nhất của tôi ở đây để xóa Permission khỏi ứng dụng ecom hoặc có cách nào tốt hơn, thông minh hơn để xử lý việc này? Ngoài ra, bất kỳ ý kiến ​​về cách tôi đã đặt ra các dự án nói chung được đánh giá cao.

+0

Tại sao phải đưa ra một ví dụ đơn giản rằng * không * minh họa sự cố? Bạn đúng; không có phụ thuộc vòng tròn ở đó, nhưng có * là * trong mã thực tế của bạn. Gửi mã thực tế cho bạn, bạn có thể chỉnh sửa bất kỳ thứ gì không áp dụng, nhưng sẽ giúp bạn xem các tệp và mô hình thực tế của bạn được đặt ra như thế nào trong dự án của bạn. –

+0

Bạn nói đúng. Tôi đã thay đổi nó ngay bây giờ. –

Trả lời

3

Vấn đề của bạn là Permission nhập Product, nhưng cả hai đều được nhập trong ecom/models/__init__.py. Bạn nên tìm cách để có hai mô hình này trong cùng một tệp hoặc tách chúng thành hai ứng dụng.

+0

Vấn đề là, tôi không thực sự * cần * những mô hình đó trong '__init __. Py', khác với syncdb để tìm các mô hình và cài đặt chúng.Tôi đoán tôi đã hy vọng tìm ra cách để tránh đưa những hàng nhập đó vào tập tin đó ngay từ đầu. –

+1

Không thể. Đó là cách duy nhất để chia nhỏ mô hình của bạn thành các tệp riêng lẻ với Django. Các nhập khẩu đó phải nằm trong '__init __. Py', về cơ bản, bạn không thể nhập chéo trong cùng một ứng dụng. Nếu hai mô hình trong cùng một ứng dụng cần nhau, chúng cần phải ở trong cùng một tệp. –

Các vấn đề liên quan