用简单的语言解释什么是Django通用视图?

25 投票
3 回答
7684 浏览
提问于 2025-04-15 20:22

这篇页面的前两段说了通用视图的目的,就是为了让我的生活更轻松,不那么单调,还能让我更吸引女性(最后一句是我自己编的):

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

我当然希望生活能更好,但通用视图到底是干嘛的呢?感觉有很多专业术语在这里被提到,反而让人更困惑,而不是解释清楚。

通用视图是不是和Ruby on Rails里的脚手架类似?介绍的最后一点似乎在暗示这个。这样说准确吗?

3 个回答

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')

现在请求的上下文会被传递过来了!这只是个开始。通用视图在你想要显示列表或详细视图时特别有用。它们会处理查询数据库和给用户发送消息等事情。

所以,通用视图是一些高级功能,帮助你从视图中创建响应。

5

通用视图让你写的代码变得更简洁。

对比一下:

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")
    )

就像你平常写的视图,它们其实都是普通的函数。如果你愿意,可以完全通过URL配置来设置这个视图,不过我觉得上面的用法更清晰一些。

作为额外的好处,你还可以得到:

  • 登录认证检查(只需设置 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
19

Django的通用视图其实就是一些普通的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

还有一些更复杂的通用视图,用于处理常见的操作,比如“显示模型列表”或者“向数据库添加模型”。

另外,因为通用视图就是函数,所以你可以在自己的视图函数中调用它们,这样可以完成“大部分工作”,当你需要的功能和通用情况稍有不同的时候,这样做会很方便。

撰写回答