使用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)
问题在于你倾向于在整个地方进行大量的进口..
答案 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文档所说:
如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身。
这也适用于ManyToMany
和OneToOne
关系。
我不认为确实存在,但我认为可能会查看django.contrib
个应用程序。他们使用模型导入。
您可能需要查看:
热门应用也使用相同的功能:
您可能还想查看social_auth
的来源,了解其中的变体:
我认为一般的经验法则是尽可能使用模型导入,但如果需要,请准备好使用字符串表示法。