在一个项目中使用Django用户认证和Taggit进行多个应用程序的开发

8
背景:我有5个独立的Django项目,我试图将它们合并成一个由几个应用程序组成的Django项目。换句话说:projA拥有appA,projB拥有appB和projC拥有appC等。我想要一个包含appA、appB和appC的主masterProj。
目前,每个应用程序连接到自己独立的数据库(应用程序不共享数据)。每个项目都使用Django用户认证、Django注册、taggit、profiles、comments和sorl-thumbnail。
我正在使用Django 1.4,并设置database routing according to this stackoverflow answer,以便在合并为一个项目后,新组合的Django项目中的每个应用程序仍能连接到自己的数据库。这一切进行得很顺利,但我开始遇到像用户认证和taggit这样的问题:
1)如前所述,每个应用程序连接到不同的数据库,每个数据库都有一个名为“auth_user”的表。然而,我发现所有对auth_user表的读/写调用(无论哪个应用程序进行读/写调用)都被路由到默认数据库(在这种情况下是appA的数据库)。
# settings.py:
DATABASES['default'] = DATABASES['appA']
DATABASE_ROUTERS = ['appA.db.DBRouter', 'appB.db.DBRouter', 'appC.db.DBRouter']

# appA/dbrouterA.py (appB, appC routers are identical this, replacing 'appA' with 'appB', etc.)
class DBRouter(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'appA':
            return 'appA'
        if model._meta.app_label == 'auth':
            return 'appA'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'appA':
            return 'appA'
        if model._meta.app_label == 'auth':
            return 'appA'
        return None

2) 假设我成功了解决路由问题,如果用户登录了appA,我不希望他们被登录到appB。我看到很多人发布了相反的问题(他们希望他们的应用程序共享用户凭据),但是有没有人成功地在同一项目中的几个独立应用程序中使用Django用户身份验证?如果是这样,你是怎么做到的?

3) 我从我的taggit代码中得到以下错误,但我还没有找到如何将“related_name”参数传递给taggit。我正在使用taggit的基本实现-没有子类化任何内容:

# appA/models.py
tags = TaggableManager(blank=True)

# appB/models.py
tags = TaggableManager(blank=True)

错误:

appA.userprofile: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.userprofile_set'. Add a related_name argument to the definition for 'tagged_items'.
appB.userprofile: Accessor for m2m field 'tagged_items' clashes with related m2m field 'TaggedItem.userprofile_set'. Add a related_name argument to the definition for 'tagged_items'.

4) 我开始觉得将所有这些应用程序组合在一起是一个很棘手的问题;在后续的开发中,我可能会遇到与sorl缩略图或尚未浮现的评论相关的问题。是否有人成功地将应用程序合并为单个项目?或者我正在尝试做一些Django根本不支持的事情?

提前感谢您的帮助!


你为什么想要将它们合并呢?在我看来,你实际上想要将它们保持分离--即使是认证表也不共享。无论如何,你至少需要构建一个新的身份验证后端,在get调用中实际使用using(),以及一个会话处理程序来知道你登录的应用程序是哪个...我的直觉告诉我这是非常未开发的领域。祝你好运! - Yuji 'Tomita' Tomita
我的最终目标是合并应用程序(指一个Django项目和一个应用程序;目前很多应用程序共享公共代码)。但作为第一步,我想将它们全部合并到一个项目中;然而,这比我想象的要困难得多。感谢提供信息! - jewelia
嗯,有趣。也许你可以先处理默认数据库中的身份验证,就像最终合并产品中所做的那样?如果你能设计一种认证接口来处理网站不同部分的单独登录,那么你的代码将从中间阶段(5个应用程序)到最终阶段(1个应用程序)时不需要更改!另外一个提示:如果你将身份验证问题与taggit问题分开,你可能会得到更多的帮助。 - Yuji 'Tomita' Tomita
taggit源代码中没有显示“related_name”,似乎这是一个未解决的问题:https://github.com/alex/django-taggit/issues/50。有一种修复方法可以在其中传递related_name.. field.rel.related_name='+'。您的Python实例需要一个唯一的属性来解析反向查找模型。将其设置为+将删除反向查找助手。 - Yuji 'Tomita' Tomita
我修改了我的模型,使每个传递的related_name都不同:tags = TaggableManager(blank=True) tags.rel.related_name = "appA" - 这解决了tags变量冲突的问题,但不幸的是tagged_items变量仍然存在相同的错误,我无法弄清楚如何将related_name传递给该变量。另外:感谢反馈有关合并和创建单个身份验证界面的建议;我现在肯定倾向于这样做 :) 这是我第一次在stackoverflow上发布帖子,所以感谢下次分开提问的提示。 - jewelia
UserProfileTaggedItem 之间的关系在哪里定义?看起来你的 appA/appB 的 UserProfile 模型通过 taggit 的方式与 TaggedItem 建立了 FK/M2M 关系,你需要在那里设置相关名称。很抱歉,taggit 的工作原理对我来说还有些困惑。1.2+ 版本中所有标签模型都有独特的应用程序相关名称,因此我不确定 FOO_set 是从哪里来的。如果您发布单独的问题,您可能会得到答案尝试,而在这里,我没有信心能够真正回答您的问题 :) - Yuji 'Tomita' Tomita
1个回答

1
Django的架构旨在围绕一个Django项目和几个Django应用程序展开。项目本身只是您的设置和主URL配置模块,而应用程序则是遵循一些文件约定的简单包。
现在,这些应用程序本身从未与特定项目耦合(虽然它们可以通过引用它们与其他应用程序耦合)。想法是允许您保留设计项目源结构的自由,并且对于大多数Django项目来说,最常见的方法之一是将Django应用程序分发到项目的顶级包下,就像大多数Python应用程序一样。这种方法使得方便地获取项目提供的所有功能的整体视图(当您应用有意义的应用标签时),创建命名空间并为开发人员提供方便和组织良好的访问特定项目源的路径。
这对于大型项目以及当您想要合并几个重复使用类似设计和方法的不同项目时非常有效。虽然这仅影响项目的结构方式,但选择是否为单个Django项目或多个Django项目配置固定集合的Django应用程序会产生一些重要影响。
当您创建Django项目时,您基本上是将Django应用程序插入到框架的仪器中,并通过配置和包括来自Django应用程序的URL和视图的映射模式来公开应用程序行为,正如我们在Web应用程序中理解的那样。
重点在于您可以按照任何适合您的方式重新组织源代码。您的程序包可以像proj.appAproj.appB等这样组织,也可以像proj.common1proj.common2proj.projA.app1proj.projA.app2proj.projB.app1这样组织,完全由您决定。
您应该知道的是,您不需要一个单一的设置和URL模块来处理数据库路由和管理数据库连接,您同样可以为每个项目提供一个设置和URL模块,引用不同的应用程序并公开不同的行为。通过每个项目的数据库设置,您已经在重复使用代码的同时,保持了每个项目的数据库数据和状态的不同。

请原谅我有些迟钝,但我真的看不出这如何回答楼主的问题...您能再解释一下吗? - David Wolever

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接