Django跨应用程序导入的公认惯例是什么

时间:2012-09-03 20:34:17

标签: python django

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

最小化循环导入的接受程序是什么,或者是否有人提出可接受的编码标准来减少他们愿意分享的内容。

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

模型

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

VS

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)

问题在于你倾向于在整个地方进行大量的进口..

2 个答案:

答案 0 :(得分:1)

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

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

我注意到我的很多模特都有一些共同的属性。例如 我更喜欢使用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应用提供了摘要 模型增加了我与celery有关的任何接口,我经常使用它。

tasks应用可以从core应用导入模型,但不能相反。

我还有一个mms应用,可以处理多媒体创建和转换(缩略图等)。 mms可以从之前的应用导入模型。所以我们现在的进口关系就是:核心 - >任务 - > 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模块分解为“微管理”应用程序 较小的模块遵循上述规则。我发现这涵盖了 我的大部分需求。

我无法评论基于课程的观点,因为老实说,我不喜欢它们,而且差不多 总是让我写更多代码而不是更少。对每一个他自己。我更喜欢使用帮手 实用函数并充分利用内部context processors之类的东西 我的观点功能。

我希望我的回答是在你的问题的背景下。

编辑:我刚刚注意到你对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不是 仅用于具有唯一的相关名称。

答案 1 :(得分:1)

关于查看代码

我不认为来自应用A的视图代码很可能会以导致循环导入的方式从应用B导入视图代码。
如果您恰好在应用A的视图中使用来自其他应用B的视图代码,那么该代码应属于views.py文件,而属于utils.py(或类似)文件。

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

关于型号代码

正如您所提到的,在不同应用的模型之间建立ForeignKey关系可能导致循环导入 对您的ForeignKey地址使用字符串表示法进行挑战,并且正如Django文档所说:

  

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

这也适用于ManyToManyOneToOne关系。

关于是否存在可接受的标准

我不认为确实存在,但我认为可能会查看django.contrib个应用程序。他们使用模型导入。

您可能需要查看:

热门应用也使用相同的功能:

您可能还想查看social_auth的来源,了解其中的变体:

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