6

Django 和相互交互的应用程序很容易遇到导入问题。我的问题很简单:

最小化循环进口的公认流程是什么,或者有没有人提出一个公认的编码标准来减少他们愿意分享的这些。

我正在寻找可以标准化的良好原则。

楷模

class Program(models.Model):
    group = models.ForeignKey(Group, related_name="%(app_label)s_%(class)s_related") 

对比

class Program(models.Model):
    group = models.ForeignKey('auth.Group', related_name="%(app_label)s_%(class)s_related") 

意见:

class ProgramDetailView(DetailView):
    """Detail view of the EEP Program"""

    def get_queryset(self):
        """Narrow this based on your company"""
        from apps.company.models import Company
        company = Company.objects.get(name="foo")
        return Program.objects.filter(company = company)

vs(这往往会导致问题..

from apps.company.models import Company
class ProgramDetailView(DetailView):
    """Detail view of the EEP Program"""

    def get_queryset(self):
        """Narrow this based on your company"""
        company = Company.objects.get(name="foo")
        return Program.objects.filter(company = company)

这样做的问题是您倾向于在整个地方进行大量导入..

4

2 回答 2

1

多年来,根据我对如何开发 Web 应用程序的观察,我对一些模式进行了标准化。

我不知道您对模块化和代码重用的标准是什么,但以下简单的规则/模式对我的一些相当大的项目有很大帮助。

我注意到我的许多模型都有一些共同的属性。例如,我更喜欢使用 UUID 而不是简单的自动递增整数作为主键。

所以我有这个抽象模型。

class UUIDModel(models.Model):
    id = UUIDField(primary_key=True, auto=True)  # There are many implementation of this on the web. Choose your favorite.

    class Meta:
        abstract = True

我的许多模型都需要activation. 所以我有另一个抽象模型,类似于:

class ActivatedModel(Model):
    is_active = models.BooleanField(default=False)

    def activate(self, save=True):
        if self.is_active:
            raise Exception('Already activated')
        self.is_active = True
        if save:
            self.save()

    class Meta:
        abstract = True

我使用许多其他抽象模型来跟踪创建时间和修改,或者是否finalized可以进一步修改某些内容等。

所有这些抽象模型都存在于core应用程序中。我就是这样称呼它的。除了core应用程序,我还有一个tasks应用程序。该tasks应用程序提供了抽象模型,可以增强我与芹菜相关的任何接口,我经常使用它。

tasks应用程序可以从应用程序中导入模型core,但反之则不行。

我还有一个mms应用程序,它处理多媒体创建和转换(缩略图等)。mms可以从以前的应用程序中导入模型。所以我们现在的导入关系是这样的:core -> tasks -> mms。

我创建的每个其他应用程序都特定于我正在处理的当前项目,并基于以前的应用程序构建。所以基本上我会尝试“单向进口”,如果你可以这么称呼的话。

我最终得到了与此类似的模型:

# models.py of an app called  "articles"

from core.models import UUIDModel, ActivatedModel
from tasks.models import ManagedTasksModel

class Article(UUIDModel, ActivatedModel, ManagedTasksModel):
    title = models.CharField()
    # blah...

如果一个应用程序变得太大,我会按照上述规则将models.py模块分解成更小的模块来“微观管理”该应用程序。我发现这可以满足我的大部分需求。

我不能评论基于类的视图,因为老实说我不喜欢它们,而且它几乎总是让我写更多的代码而不是更少的代码。各有各的。我更喜欢使用辅助实用程序函数,并在我的视图函数中充分利用上下文处理器之类的东西。

我希望我的回答是在你的问题的范围内。

编辑:我刚刚注意到您的使用related_name我认为错过了该选项的要点。请参见以下示例:

class Message(models.Model):
    sender   = models.ForeignKey(User, related_name='messages_sent')
    receiver = models.ForeignKey(User, related_name='messages_received')
    body     = models.Textfield()

使用上面的模型我们可以做到这一点,可读性很强:

u1 = User.objects.get(...)
received = u1.messages_received.all()

...它描述了这种关系的功能目的。所以related_name不仅用于具有唯一的相关名称。

于 2012-09-03T21:44:31.970 回答
1

关于查看代码

我认为来自应用程序 A 的视图代码不太可能以导致循环导入的方式从应用程序 B 导入视图代码。
如果您碰巧在应用 A 的视图中使用来自另一个应用 B 的视图代码,那么该代码应该属于一个views.py文件,但属于utils.py(或类似)文件。

应用 A 的模型代码更不可能从应用 B 导入视图代码,因此在应用 B 的视图代码中对应用 A 的模型代码使用顶级导入是完全可以的。

关于型号代码

但是,正如您所提到的,ForeignKey来自不同应用程序的模型之间存在关系可能会导致循环导入。
使用字符串表示法来ForeignKey挑战您的地址,正如 Django 文档所说:

如果您需要在尚未定义的模型上创建关系,您可以使用模型的名称,而不是模型对象本身。

这也适用于ManyToManyOneToOne关系。

关于是否存在公认标准

我不认为真的存在一个,但我认为也许查看django.contrib应用程序是相关的。他们使用模型导入。

您可能想查看:

流行的应用程序也使用相同的功能:

您可能还想查看以下social_auth变体的来源:

我认为一般的经验法则是尽可能使用模型导入,但如果需要,请准备好使用字符串表示法。

于 2012-09-03T22:23:25.880 回答