【问题标题】:django: modifying/extending 3rd party appsdjango:修改/扩展 3rd 方应用程序
【发布时间】:2012-01-15 23:01:35
【问题描述】:

一个新手 django 问题

我想使用 3rd 方应用程序,但我需要对其进行一些修改(在本例中,该应用程序是 django-registration,我需要更改一些内容,例如允许在没有确认电子邮件的情况下进行注册)

最初,我只是将应用程序安装在通用站点包文件夹中,并在那里更改了代码。现在我将代码放在了 bitbucket 上,我需要一种能够以可用的方式将我的 mod 保存在存储库中的方法,并且上传完整的 python 代码听起来不是一个好主意。

我想最好的方法是将第 3 方应用程序保留在站点包中,并在我的项目中创建一个应用程序来保留我的更改。就我而言,我会在我的项目中创建 my-django-registration,然后在我的代码中需要它时将其导入,而不是 django-registration。

我还阅读了有关 virtualenv 的信息,但我认为这主要用于能够在同一台机器上使用多个环境(事实上,它建议不要更改安装在 virtualenv 中的模块),并且对我没有帮助将我的更改保存在存储库中。

欢迎任何cmets! 谢谢

【问题讨论】:

    标签: django


    【解决方案1】:

    一般来说,您应该重用和覆盖 3rd 方应用中的行为,而不是修改它们的来源。

    您最常遇到的是应用发布的模型不一定能满足您的需求,但可以完成大部分工作;您将拥有几乎完美的表格,但需要一点点东西;如果你能改变一件事,你就会拥有完美的观点;您将拥有健全的 URL,但您需要从它们那里获得更多信息。

    在大多数情况下,这只需要您创建一个自定义应用程序并重新连接所有内容。发送您自己的 URL,这些 URL 映射到您已扩展并覆盖自定义行为方法的视图;为它提供Meta 正在使用您从原始模型扩展的新模型的模型表单;等等……

    这只是您可以做的冰山一角,您的创意还有更多方法。我可以告诉你我是如何使用RegistrationProfile 模型的example,但提供了我自己的 URL 模式和一个处理注册过程的基于类的自定义视图。

    现在,virtualenv 发挥作用的地方在于,您很可能会使用 piprequirements file format 中指定和提供所需的依赖项。那时你想说:“我已经扩展了 django-registration 应用程序,但它不能与任何版本一起干净地工作。它必须是版本 X”,或者,“从提交 Y 的存储库中签出”。

    【讨论】:

    • 这应该是正确的答案。正如接受的答案所建议的那样,分叉不是要走的路。
    • 在某些情况下,分叉是必要的。如果包没有维护,但它不再兼容最新的Django,这是不可避免的。
    【解决方案2】:

    This blog post 解决了这个问题非常有帮助。为方便起见,我在这里复制粘贴:

    您无需接触外部应用代码

    您不应该从外部应用程序编辑代码。除非你先在 github 上 fork 。

    那么,如何在不分叉的情况下覆盖:

    覆盖模板

    如果您想覆盖templates/userena/activate_fail.html,那么您所要做的就是创建自己的templates/userena 目录并在其中创建自己的activate_fail.html

    覆盖网址

    您应该在外部应用程序中检查的第一件事是它的 urls.py。正确编码的视图应该支持大量参数。例如,userena 有一个带有这样签名的注册视图(在撰写本文时):

    def signup(request, signup_form=SignupForm,
           template_name='userena/signup_form.html', success_url=None,
           extra_context=None):
    

    这意味着您可以替换注册视图使用的表单。为此,请打开您的 urls.py,在顶部添加我们需要的内容:

    from userena import views as userena_views
    from yourforms import YourSignupForm
    

    然后,找到包含外部应用程序的网址,例如:

    url(r'^userena/', include('userena.urls')),
    

    在此之前,添加您的网址覆盖:

    url(r'^userena/signup/$', userena_views.signup, {'signup_form': YourSignupForm}, name='userena_signup'),
    url(r'^userena/', include('userena.urls')),
    

    现在,当访问者点击 /userena/signup/ 时,您的自定义 url 定义将首先被点击。这意味着/userena/signup/ 将使用 YourSignupForm 而不是 userena 的注册表单。

    这个技巧适用于任何视图参数。您最应该看到的是:

    • template_name: 让你更改模板名称
    • extra_context: 让你添加一个将被添加到 上下文

    几乎每个视图都应该有这些参数。

    覆盖视图

    覆盖视图需要覆盖要替换的视图的 url。如果您希望使用自己的注册视图,则只需覆盖 url:

    import yourviews
    
    # ...
    url(r'^userena/signup/$', yourviews.yoursignup, name='userena_signup'),
    url(r'^userena/', include('userena.urls')),
    

    装饰视图

    装饰视图类似于覆盖视图,但会重用外部应用的视图。基本上,它与覆盖视图相同(见上文),但您的视图看起来像这样

    from userena import views as userena_views
    
    def yoursignup(request):
        # do stuff before userena signup view is called
    
        # call the original view
        response = userena_views.signup(request)
    
        # do stuff after userena signup view is done
    
        # return the response
        return response
    

    分叉应用

    如果你不熟悉 pip 和 virtualenv,请先阅读关于使用 pip 和 virtualenv 的帖子。

    例如:

    • 您这样安装了 django-userena:pip install django-userena
    • 首先你应该卸载它:pip uninstall django-userena
    • 然后进入应用的 github 页面
    • 点击分叉按钮
    • 这将使您成为一个包含 django-userena 副本的存储库
    • 这样安装:pip install -e git+git@github.com:your-username/django-userena.git#egg=django-userena
    • 然后就可以编辑yourenv/src/django-userena中的代码了
    • 推送您的提交

    致作者的功劳!

    【讨论】:

    • 这篇文章很有帮助,正是我想要的!
    • 覆盖模板:似乎还需要一件事:在 INSTALLED_APPS 中,您的应用程序(使用更改的模板)应该早于第 3 方应用程序(使用原始模板)。
    【解决方案3】:

    我认为完成您所寻找的最简洁的方法是 fork django-registration,并在您的应用中使用 fork 而不是原始项目。

    话虽如此,您可以在 django-registration 中进行非电子邮件注册,而无需更改应用程序的代码。我通过创建自定义registration backend 来完成它,该registration backend 将用户设置为在创建时激活。 Here你可以看到其他方法来做同样的事情。

    【讨论】:

    • 对,我所做的更改正是莱昂内尔对您链接到的问题的解决方案中的更改。分叉是指(以某种方式)创建我自己的 django-registration 分支并在那里进行更改吗?我也是 mercurial 的新手,不确定我是否可以在 3rd 方存储库上创建自己的分支,听起来有点矫枉过正。我猜想在我的项目中有一个带有这些更改的本地应用程序会以更简单的方式实现相同的效果,尽管可能不太明确
    • bitbucket 和 GitHub 等开源共享网站提供了创建分叉的选项(正如您所说的主项目的一个分支)。只需单击几下即可。这可能有点矫枉过正,但我​​个人认为这比将整个应用程序复制到一个不相关的项目中要简单得多。还认为您可能希望在其他应用程序中使用相同的更改,并且您希望避免每次都复制粘贴修改后的应用程序。
    • 我刚试了一下,确实是点击了几下:转到原始存储库,单击分叉,添加您的描述,然后您就拥有了您帐户下分叉的存储库的“副本” ,您可以在其中进行并提交您的更改,我想也可以轻松地合并来自主干的任何更改。是的,这绝对是一个更简洁的解决方案,谢谢!
    • 但是,您如何在主项目的存储库中指出它需要应用程序的特定分支? (我想我一般也可以问你如何表明它需要特定的应用程序)。我想为此你最好在你的项目中复制应用程序,但我想你会失去与原始 3rd 方存储库的连接
    • 您可以从存储库 url 进行 pip 安装。我已经看到在您的主项目中有一个 requirements.txt 的模式,其中包含用于安装依赖项的 pip 命令列表(作为应用程序名称或存储库 URL)。您可能应该将它与 virtualenv 结合使用或检查其他方法;我认为这并不会真正影响复制第三方应用程序的分叉问题。
    猜你喜欢
    • 2011-03-26
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    相关资源
    最近更新 更多