我刚刚完成了第二次使用Django教程,现在我已经更加清楚地理解了这些内容。但是,我还不清楚网站内的应用程序是如何互相交互的。
例如,假设我正在编写一个博客应用程序(显然是一个相当受欢迎的活动)。博客文章和评论倾向于一起出现,但它们非常独特,应该将它们构建到单独的应用程序中,这就是Djano开发的一般理念。
考虑以下示例。实际上,我实际上并不会自己编写评论应用程序,因为网上已经存在好的代码,但这是出于演示/练习的目的:
mysite的/博客/ models.py
from django.db import models
class post(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
content = models.TextField()
mysite的/评论/ models.py
from django.db import models
from mysite.blog.models import post
class comment(models.Model):
id = models.AutoField()
post = models.ForeignKey(post)
author = models.CharField(max_length=200)
text = models.TextField()
我上面写的是什么,从另一个应用程序导入模型并将其设置为外键,Django应用程序如何交互?或者是否有一个不同/更好的方法来构成一个网站进行交互?
更新
根据一个响应中的建议,我正在阅读contrib.contenttypes的文档。如果我正确读到这个,我可以像这样重写我的示例评论应用程序:
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contentypes import generic
class comment(models.Model):
id = models.AutoField()
author = models.CharField(max_length=200)
text = models.TextField()
content_type = models.ForeignKey(ContentType)
content_object = generic.GenericForeignKey(content_type, id)
这是正确的吗?
答案 0 :(得分:21)
看一下django的内置contenttypes framework:
django.contrib.contenttypes
它允许您将应用程序开发为独立单元。这就是django开发人员用来允许django的内置comment framework将注释附加到项目中的任何模型的内容。
例如,如果您有一些内容对象要“附加”到不同类型的其他内容对象,例如允许每个用户在博客帖子,图像或用户个人资料上留下“最喜欢的”星标,那么可以使用generic relation field创建Favorite
模型,如下所示:
from django.db import models
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class Favorite(models.Model):
user = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
通过这种方式,您可以将任何用户的Favorite
星添加到项目中的任何模型。如果您想通过收件人模型类添加API访问权限,您可以在收件人模型上添加reverse generic relation field(尽管这会“耦合”您说要避免的两个模型),或者执行使用收件人实例的Favorite
和content_type
在object_id
模型中查找,有关示例,请参阅official docs。
答案 1 :(得分:3)
“我上面写的是什么,从另一个应用程序导入模型并将其设置为外键,Django应用程序如何交互?”
是的。适合我。
我们有大约10个相互借用的应用程序。
这会在我们的单元测试脚本中产生一种依赖性。
看起来像这样。
“所有权”。我们有一个简单的数据所有权应用程序,它定义了其他应用程序所依赖的核心所有权概这里有一些简单的表格。
“东西”。 [不是真名]。我们的东西应用程序拥有不同用户组拥有的数据元素。这个应用程序的模型实际上有几个复杂的表。这取决于“所有权”。
“表”。 [不是真名]。我们的一些用户创建了相当复杂的离线模型(可能包含电子表格),并在“表格”中上传了该建模的结果。这有一组相当复杂的表。这取决于“所有权”。
“结果”。 [不是真名]。我们的结果基于拥有者的事物。结果基于事物和表格,并且是对客户请求的响应。这不是太复杂,也许只有两三个核心表。这取决于“事物”和“表”。不,它不是完全独立的。但是,它取决于其所依赖的其他事物的更多变化。这就是为什么它是分开的。
“处理”。我们安排和监控大批量工作。这是在这个应用程序中。它非常通用,可以多种方式使用。它完全独立。
“欢迎”。我们有一个“欢迎”应用程序,它提供了大量静态页面。这没有太多的表。但它是第二个化身,因为第一个太复杂了。它完全独立。
依赖应用程序之间的唯一关系是一些表名。只要我们保留这些表(及其键),我们就可以按照我们认为合适的方式重新安排其他应用。
答案 2 :(得分:3)
使某些应用程序依赖于另一个应用程序没有任何错误(imho)。毕竟,应用程序只是一组模型上的操作。你只需要总是知道哪个应用程序取决于哪个应用程序(我想你可以称之为依赖关系图)。
您可以使用contenttypes框架实现松散耦合。它允许应用程序真正可移植/可插拔,但仍与其他应用程序集成。
我写了一个评论应用程序(是的,我重新发明了轮子),可以集成到任何其他应用程序中,在页面模板中有几行应该发布评论(使用自定义标签)。< / p>
假设您希望模型“线程”可插入任何其他模型。我的想法是创建e通用外键(请参阅django文档),并编写一个小函数,它接受任何对象并返回与其对应的“线程”(或者在必要时创建一个),并编写一个自定义模板标记,使用该功能,例如{% get_thread for arbitrary_object as thread %}
。所有帖子都与一个与该对象相关的线程相关,该线程可以是任何类型。
您可以将“线程”对象视为一种代理,因此它不是将帖子与某个“文章”或“博客帖子”相关联,而是与线程相关,这是一个抽象的从某种意义上说,是是一个线程?这只是一个帖子的集合。然后,线程允许自己与任何对象相关,而不管其类型如何。 (虽然它不止于此,它可以保存额外的信息,例如允许/禁止匿名。帖子,关闭/打开页面上的评论等。)
修改强>
以下是如何使用内容类型框架创建通用外键:
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
class Thread( models.Model ):
object_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
object = generic.GenericForeignKey('object_type', 'object_id')
通过利用django假设所有对象实现的隐式“公共”接口,可以使其更加“透明”。
#inside the Thread class:
def __unicode__(self):
return unicode(self.object)
def get_absolute_url(self):
return self.object.get_absolute_url()
答案 3 :(得分:2)
您的代码似乎正确无误。我会在博客应用中保留帖子和评论。我并不是说这是 Django方式,但这些模型足够接近于同一个应用程序。
我会分开一个应用程序if;
另一方面;拥有许多小应用程序(例如具有单一模型的应用程序和两个视图)很难阅读和维护恕我直言。
这取决于项目类型和应用类型。例如,如果应用程序隐式依赖于另一个(即非通用)导入,则可以使用来自其他应用程序的引用。在这种情况下,第二个应用程序可能会单独安装,但第一个应用程序需要存在第二个应用程序。
如果您想使应用程序具有高度可重用性和通用性,例如评论应用程序,则可能需要集成一些设置机制。也许一些新的设置或额外的URL配置,或模型上的特殊指令/方法...... django.contrib.admin
就是一个很好的例子。
如果没有必要,应用程序不应该进行交互。设计应用程序以避免不必要的耦合非常有用。它可以提高应用程序的灵活性并使其更易于维护(但可能需要更高的集成成本)。