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


74

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

我可以做类似的事情吗?

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)
罗伯特·索利斯

Answers:


56

View函数应将呈现的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)
    ...

23
如果被调用的视图位于第三方应用程序中,我们该怎么办?
Sandip Agarwal

1
赛斯,如何在模板中调用view1的变量或如何使用view1的变量进行显示
user2086641 2013年

在某些情况下,您可能希望视图调用另一个视图,例如使用视图下载文本/ csv文件或使用AJAX更新视图模板的一部分时(在这种情况下,不会直接调用第二个视图)从第一个视图开始,而是在视图的模板html文件中通过一些jquery或js)
Samwise Ganges

73

当然,只要说完了,您的视图就会返回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中启动了一些逻辑,对响应对象什么也不会做,对吧?
多米尼克·瓜迪奥拉

5
是的,就是这个主意。view1可能在模型或其他物体上运行。赛斯有一个正确的主意。最好是从两个视图中删除通用功能,然后将其放入一个函数中,view1然后view2两者都调用,然后它们返回各自的HttpResponse对象。无需生成将不使用的HttpResponse-尤其是如果其中包含需要大量查询的模板时,尤其如此。
布雷迪

@brady,如何在模板中调用view1的变量或如何使用view1的变量来显示
user2086641 2013年

3
尽管塞思(Seth)的想法正确,但是如果需要从第三方应用程序调用视图,那么解决方案就是正确的选择!
Diego Ponciano

1
第二种模式不好。您有时可以从view2调用view1,但是如果这样做,应该只是返回view1。关键是您向view1传递了一些其他参数,这些参数通常不是从url获得的(extra_context,template,success_url等)。这里view2充当view1的代理视图。如果您需要view1的全部逻辑(否则应该使用逻辑提取),那几乎是唯一允许的模式。在第三个应用程序中,您只需要查看并完全重写即可,如果您需要更改。使用基于类的视图,在这种情况下可以使用继承,这样更干净。
风土

9

更好的方法是使用模板系统。结合@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
滚刀

2

没有基于类的视图:

def my_view(request):
    return call_another_view(request)

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

具有基于类的视图

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

class CallAnotherView(View):
    ...

这应该是第一位的,my_view(request)还是CallAnotherView(View)
盖德(Gathide)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.