【问题标题】:Multiple Instances of a django app, does django support thisdjango应用程序的多个实例,django是否支持这个
【发布时间】:2012-01-14 00:08:32
【问题描述】:

我在 django 中编写了一个简单的反馈应用程序。它并不特别复杂,基本上它允许经过身份验证的用户编写带有主题行的快照消息并通过表单提交该消息。然后,我允许选定组中的人员查看用户提交的反馈。将来我可能会添加更多功能,但现在它可以满足我的需求。

我的问题来了,我正在构建的网站有多个我想使用反馈应用程序的地方,例如我有一个“你觉得这个网站怎么样?” /dev/feedback/ 的一种页面 我在“/support/feedback/”也有一个用于客户支持反馈的页面 目前我刚刚将代码从我的mysite.apps.dev.feedback 复制到mysite.apps.support.feedback

问题是现在这已经创建了相同代码的两个单独副本。尽管刚刚编写了应用程序,但两个版本已经开始出现分歧,这很烦人。我的问题只是如何在具有不同数据库模型的 django 站点中创建同一应用程序的多个实例?

我发现一些相关但没有帮助的资源是 https://docs.djangoproject.com/en/dev/topics/http/urls/Reversing namespaced URLs in Django: multiple instances of the same app 第一页没有提供太多关于这个问题的信息,第二页提供了一些笨拙和不切实际的解决方案,这些解决方案似乎既不相关又需要更多工作比他们的价值。有没有一种正确的方法来实现同一个 django 应用程序的多个实例?

【问题讨论】:

    标签: python django django-models django-apps


    【解决方案1】:

    单一模型方法

    我个人会尝试将其保留为一个应用程序,并拥有一个可以处理从多个位置发布/适当标记它们的视图。

    正如 S.Lott 所说,这是要走的路。如果您对在其他情况下将代码保留在一个位置的方法感到好奇,我将提供替代方案。

    例如,您可以在模型中添加一个category 字段,设置一个接受URL 中的参数(例如/(?P<category>\w+/feedback/$)的单个url conf,并让视图简单地用适当的类别标记反馈。

    class MyForm(forms.ModelForm):
        class Meta:
            model = Feedback
    
    def my_view(request, category):
        form = MyForm(request.POST or None)
        if request.method == 'POST':
            if form.is_valid():
                feedback = form.save(commit=False)
                feedback.category = category
                feedback.save()
                return http.HttpResponse("Thanks for posting!")
        return render(request, "mytemplate.html", {'form': form})
    
    # urls.py
    (r'^(?P<category>\w+)/feedback/$', 'my_view')
    
    # user can visit dev/feedback or support/feedback and the feedback will be tagged appropriately
    

    抽象基类

    另一种解决方案是构建abstract base class,然后为不同的表创建子类。这应该可以解决您的代码不同步的问题。

    您将拥有一个抽象模型(没有表格),您的单独应用中的“真实”模型将基于该模型。

    动态生成的视图

    如果您必须有单独的模型,您可能会编写一个动态构造的视图。

    def view_generator(model_class):
        class MyForm(forms.ModelForm):
             class Meta:
                  model = model_class
    
        def my_view(request):
            form = MyForm(request.POST or None)
            if request.method == 'POST':
                if form.is_valid():
                    form.save()
                    return http.HttpResponse("Thanks for posting!")
            return render(request, "mytemplate.html", {'form': form})
        return my_view
    
    
    # urls.py
    from foo import view_generator
    
    (r'^my_first_feedback_form', view_generator(Model1))
    (r'^my_second_feedback_form', view_generator(Model2l))
    

    【讨论】:

    • “单一模型”值得所有强调。一个例子会有所帮助。其他方法通常比它们需要的更困难和复杂。
    【解决方案2】:

    如何在具有不同数据库模型的 django 站点中创建同一应用的多个实例?

    你不应该。

    您只需使用简单的from feedback.models import Feedback 在其他两个应用程序中使用反馈应用程序模型。

    然后您的support 应用程序可以创建、检索、更新和删除反馈对象。

    您的dev 应用同样可以创建、检索、更新和删除反馈对象,因为它导入了模型。

    这就是所需的全部内容:import

    【讨论】:

      【解决方案3】:

      感谢 Yuji Tomita 的非常彻底的回答,我的最终解决方案非常接近他的建议,但有足够的不同,我认为如果其他人遇到与我相同的情况,我会将其作为另一种选择发布。

      首先放在我的mysite.apps.feedback.models 文件中

      class Feedback( models.Model ):
         subject = models.TextField( max_length=100 )
         body = models.TextField( max_length=100 )
         # Some other stuff here...
         # Finally I used the suggestion above and created a field which I 
         # use to label each entry as belonging to a specific instance of the app.
         instance_name = models.TextField( max_length=20 )
      

      在我的mysite.apps.feedback.views 文件中

      def save_message( request, instance_name ):
          if request.method == 'POST':
              form = FeedbackFrom( request.POST )
              if form.is_valid():
                  form.instance.instance_name = instance_name
                  form.save()
                  return render("feedback/thanks.html")
               else:
                   return render("feedback/submit.html", {'form':form })
           else:
               return render("feedback/submit.html",{'form':FeedbackForm()})
      
      @user_passes_test( is_staff )
      def all_messages( request, instance_name ):
          messages = Feedback.objects.filter( instance_name = instance_name )
          return render("feedback/view_all.html",{'feedback':messages} )
      

      在我的mysite.apps.dev.urls 文件中

      url(r'^feedback/', include('mysite.apps.feedback.urls'),
          {'instance_name':'dev'}),
      

      在我的mysite.apps.support.urls 文件中

      url(r'^feedback/', include('mysite.apps.feedback.urls'),
          {'instance_name':'support'}),
      

      这将按应用实例分隔反馈消息。请注意,我的实际代码更复杂,但这应该足以让任何有类似问题的人快速启动并运行解决方案。希望这对处于类似情况的任何人都有用。再次感谢 Yuji Tomita 提供此解决方案所依据的建议。

      【讨论】:

        猜你喜欢
        • 2012-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-21
        • 2023-03-06
        • 2012-11-10
        • 2021-08-08
        • 2012-05-23
        相关资源
        最近更新 更多