我可以从另一个视图中调用一个视图吗?

Posted

技术标签:

【中文标题】我可以从另一个视图中调用一个视图吗?【英文标题】:Can I call a view from within another view? 【发布时间】:2011-06-16 01:14:46 【问题描述】:

我的一个视图需要添加一个项目以及其他功能,但我已经有另一个视图专门添加一个项目。

我可以这样做吗:

def specific_add_item_view(request):
    item = Item.objects.create(foo=request.bar)

def big_view(request):
    # ...
    specific_add_item_view(request)

【问题讨论】:

我认为它的使用更简单:return specific_add_item_view(request) 【参考方案1】:

如果你这样做:

def calledView(bar):
    ...
    return Response(...)

def base_view(request):
    resp = add_stuff(request)
    ...

你可能会得到这个错误

request 参数必须是 django.http.HttpRequest,不是rest_framework.request.Request

所以你应该这样做:

def calledView(request):
    ...
    return Response(...)

def base_view(request):
    resp = add_stuff(request._request)
    ...

【讨论】:

【参考方案2】:

你可以这样做:

def foo(req):
  # code
def index(req):
  return foo(req)

【讨论】:

【参考方案3】:

没有基于类的视图:

def my_view(request):
    return call_another_view(request)

def call_another_view(request):
    return HttpResponse( ... )

与class based views:

def my_view(request):
    return CallAnotherView.as_view()(request)

class CallAnotherView(View):
    ...

【讨论】:

哪个应该先出现,my_view(request)CallAnotherView(View) Gathide 任何一个命令都可以,由你决定,哪个更清楚【参考方案4】:

更好的方法是使用模板系统。结合@Seth 和@brady 的想法:

def specific_add_item_view(request, extra_context_stuff=None):
    Item.objects.create()
    context_variables =  # obviously want to populate this
    if extra_context_stuff:
        context_variables.update(extra_context_stuff)
    return render(request, 'app_name/view1_template.html', context_variables)

def bigger_view(request):
    extra_context_stuff = 'big_view': True
    return specific_add_item_view(request, extra_context_stuff)

而您的 app_name/view1_template.html 可能包含条件模板标签

% if big_view %
<p>Extra html for the bigger view</p>
% endif %

【讨论】:

感谢@Neceros 指出最近的 django 版本弃用了 render_to_response 以支持 render【参考方案5】:

视图函数应该将呈现的 HTML 返回给浏览器(在 HttpResponse 中)。在视图中调用视图意味着您(可能)进行两次渲染。相反,只需将“添加”分解到另一个不是视图的函数中,并让两个视图都调用它。

def add_stuff(bar):
    item = Item.objects.create(foo=bar)
    return item

def specific_add_item_view(request):
    item = add_stuff(bar)
    ...

def big_view(request): 
    item = add_stuff(bar)
    ...

【讨论】:

如果被调用的视图在第三方应用中怎么办? Seth,如何在模板中调用view1的变量或如何利用view1的变量显示 在某些情况下,您希望视图调用另一个视图,例如使用视图下载文本/csv 文件或使用 AJAX 更新视图模板的一部分时(在这种情况下第二个视图不会直接从第一个视图调用,而是由视图模板 html 文件中的一些 jquery 或 js 调用)【参考方案6】:

当然,只要说完了,您的视图就会返回一个 HttpResponse 对象。以下是完全有效的:

def view1(request):
    # do some stuff here
    return HttpResponse("some html here")

def view2(request):
    return view1(request)

如果您不想从第一个视图返回 HttpResponse,那么只需将其存储到某个变量中即可忽略:

def view1(request):
    # do some stuff here
    return HttpResponse("some html here")

def view2(request):
    response = view1(request)
    # do some stuff here
    return HttpResponse("some different html here")

【讨论】:

只是为了澄清你在做什么:在第二个例子中,你只是在 view1 中启动了一些逻辑,不会对响应对象做任何事情,对吧? 是的,就是这样。 view1 可能对模型对象或其他对象进行操作。不过,赛斯的想法是正确的。最好从两个视图中取出通用功能并将其放入 view1view2 都调用的函数中,然后它们返回各自的 HttpResponse 对象。无需生成不会使用的 HttpResponse - 特别是如果其中包含需要大量查询的模板。 @brady,如何在模板中调用view1的变量或如何利用view1的变量显示 虽然 Seth 的想法是正确的,但如果需要从第三方应用调用视图,您的解决方案就是最佳选择! 第二种模式不好。您偶尔可以从 view2 调用 view1,但如果这样做,它应该只是 return view1。关键是您将一些额外的参数传递给 view1,它通常不会从 url (extra_context、template、success_url,...) 获得。这里 view2 充当 view1 的代理视图。如果您需要 view1 的整个逻辑(否则应该使用逻辑提取),这几乎是唯一允许的模式。如果需要更改,您应该从第三个应用程序中查看并完全重写它。使用基于类的视图,您可以在这种情况下使用继承,因此更简洁。

以上是关于我可以从另一个视图中调用一个视图吗?的主要内容,如果未能解决你的问题,请参考以下文章

从另一个视图调用一个类

从另一个视图调用表视图函数

从另一个视图调用拆分视图

当我从另一个视图控制器调用时,为啥我的表视图为零?

iPhone - 从另一个视图控制器调用函数

添加注释以从另一个视图映射