【问题标题】:In plain English, what are Django generic views?用简单的英语来说,什么是 Django 通用视图?
【发布时间】:2011-01-27 02:31:35
【问题描述】:

本页的前两段解释说,通用视图应该让我的生活更轻松,不那么单调,让我对女性更具吸引力(最后一段是我编造的):

https://docs.djangoproject.com/en/1.4/topics/generic-views/

我完全是为了改善我的生活,但通用视图实际上有什么作用?似乎有很多流行语被抛出,这比他们解释的更令人困惑。

通用视图是否类似于 Ruby on Rails 中的脚手架?介绍中的最后一个要点似乎表明了这一点。这是一个准确的说法吗?

【问题讨论】:

    标签: python django django-generic-views


    【解决方案1】:

    Django 通用视图只是执行 Web 应用程序中非常常见的事情的视图函数(常规的旧 python 函数)。

    根据您正在构建的应用类型,它们可以让您免于编写大量非常简单的视图。

    例如,direct_to_template 通用视图仅使用 RequestContext 呈现模板(这意味着模板可以访问有关请求的信息,例如当前用户等)。

    举个简单的例子,你可以这样写:

    # urls.py
    url('^some-url/$', some_view)
    
    # views.py
    def some_view(request):
        return render_to_response('template_name.html', context_instance=RequestContext(request))
    

    仅此:

    # urls.py
    url('^some-url/$', direct_to_template, {'template': 'template_name.html'})
    
    # views.py doesn't need any code for this view anymore
    

    还有更复杂的通用视图用于常见操作,例如“显示模型列表”或“将模型添加到数据库”。

    此外,由于通用视图只是函数,因此当您需要与通用情况有点不同的东西时,您可以在自己的视图函数中调用它们来完成“大部分工作”。

    【讨论】:

    • 谢谢,TM。他们应该将此添加到文档中:)。不过,我并没有完全接受通用视图。您涉及 direct_to_template 的示例并没有节省太多代码(2 行),您仍然需要手动指定模板。不好的部分是它使你的应用程序更难理解,因为它要求我对 Django 的了解比完成这个简单任务所必需的更多。
    • @allyourcode 使用更复杂的视图可以节省更多代码,我选择了一个非常简单的示例。此外,对于那些对模型进行操作的视图,它们将根据命名约定自动选择一个模板(或者如果您不想遵循约定,可以将其覆盖)。有关更多示例,请参阅docs.djangoproject.com/en/1.1/ref/generic-views。我建议从头开始编写其中的一些视图,然后进行比较。它们都不是庞大而复杂的,编写和调试只是少了一件事。
    • 再次感谢,TM。我已经在查看 Django 开发版本的文档了。
    • 我可以看看你是否有很多单调的通用视图要创建,它可能很有用(也许可以节省一些时间)但对于简单的应用程序/项目,我发现它们不是那么有用并且可能不太可读。
    【解决方案2】:

    回答您的第二个问题:不,通用视图与 RoR 中的脚手架无关。顾名思义,脚手架类似于代码生成。通用视图是另一回事。

    我对通用视图的主要用途是作为非常基本的render_to_response 函数的更高级别的替换。这就是您可以使用render_to_response 编写简单视图的方法:

    def my_view(request):
        return render_to_response('my_template.html')
    

    但这是非常基本的!例如,模板将无法访问请求上下文,除非您明确传递它。

    因此我更喜欢使用通用视图:

    def my_view(request):
        return direct_to_template(request, template='my_template.html')
    

    现在请求上下文将被传递!这只是一个开始。例如,当您想要显示列表或详细视图时,通用视图会派上用场。他们将管理查询数据库、向用户发送消息等。

    因此,通用视图是高级函数,可帮助您从视图创建响应。

    【讨论】:

    • 通用视图可能涉及代码生成,但它们似乎扮演着相似的角色。在旧版本的 Rails 中,可以在控制器中声明脚手架(Django 术语中的视图)。这将动态地为控制器提供一堆方法,允许用户在相应的模型上执行基本的 CRUD 操作。
    • 我假设您的意思是“通用视图可能涉及代码生成,但它们起着类似的作用”。正如我所说,我宁愿说通用视图......有助于从视图中创建响应。一种可能的应用是用于 CRUD 操作。但是请注意,您仍然必须编写其余代码,因此它绝对不是脚手架。此外,如果您在响应创建中有重复性,编写自己的通用视图也是有意义的。
    • +1 用于提及如何在您的函数中使用通用视图。特别是。调用 update_object 视图对我来说是两全其美:清晰的代码,而且仍然很短。
    • 嗯,但是当我在 my_template.html 上尝试类似的操作时不起作用:{{request.user}} 我做错了什么?
    【解决方案3】:

    通用视图允许您编写更短的代码。

    比较:

    from django.http import HttpResponse, HttpResponseRedirect, Http404
    from django.shortcuts import render_to_response, get_object_or_404, redirect
    from myapp.models import Context
    
    def edit(request, item_id):
        object = get_object_or_404(Context, pk=item_id)
    
        if request.method == 'POST':
            form = ContextForm(request.POST, instance=object)
            if form.is_valid():
                form.save()
                return redirect('myapp-context-index')
        else:
            form = ContextForm(instance=object)
    
        return render_to_response("myapp/context/edit.html", {'object': object, 'form': form})
    

    与:

    from django.core import urlresolvers
    from django.views.generic.create_update import update_object
    from myapp.models import Context
    
    def edit(request, item_id):    
        return update_object(request,
            object_id=item_id,              
            form_class=ContextForm,            
            template_name="myapp/context/edit.html",
            post_save_redirect=urlresolvers.reverse("myapp-context-index")
        )
    

    就像您的正常视图一样,它们只是正常的功能。如果您愿意,可以在 URLconf 中完全配置视图,通过我发现上面的这种用法更清楚一些。

    作为奖励,您还可以获得:

    • 登录验证检查(通过login_required=True
    • 来自django.contrib.messages 的成功状态消息。
    • 检查错误的代码更少。
    • 当您提供model 参数而不是form_class 时,默认ModelForm

    template_name 的默认值为“appname/model_form.html”,但这对我来说有点太多了。


    这是他们共享的表单类:

    class ContextForm(forms.ModelForm): 
        """The form for a context"""
        class Meta:
            model = Context
            exclude = ('collection',)
    
        def save(self, commit=True):
            """Overwritten save to force collection_id to a value"""
            model = super(ContextForm, self).save(commit=False)
            model.collection_id = 1
            if commit:
                model.save()
            return model
    

    【讨论】:

    • 感谢您的解释。这是一个可能有用的示例。
    猜你喜欢
    • 2015-08-13
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-24
    • 1970-01-01
    • 1970-01-01
    • 2017-08-10
    相关资源
    最近更新 更多