问题
我想通过在另一个视图中调用视图(捕获响应并提取呈现的内容)到字符串来呈现任意视图。 问题是我想在呈现该视图期间让虚拟用户“登录”,同时更改请求中的一些其他小事。 我想避免的是完全从头开始构建请求,因为我在父视图中有90%的请求将是相同的。
我想知道就最佳做法而言,我应该如何解决这个问题,以及技术上的问题?
我现在正在考虑这样的事情:(但我不禁觉得这太可怕了,而且必须有更好的方式,我根本想不到它)
查看内容...
记录当前用户
创建/登录虚拟用户
以某种方式修改请求
将视图渲染为字符串
注销虚拟用户
重新登录原始用户
结束观点...
有什么想法吗?或指向更好方向的指针?
谢谢, dennmat
答案 0 :(得分:2)
根据您在视图中依赖于从请求中获取信息的程度,最好只创建一个函数来完成所有视图的脏工作,并让您的真实视图传递给值它需要进入这个功能。因此,不是采用请求的视图函数,而是创建另一个需要用户的函数:
def _real_view(user):
return render_to_response('template.html', {'user' : user})
def view(request):
# Now both of these are possible...
response = _real_view(User.objects.get(5))
response = _real_view(request.user)
return response
然后,当您想要使用其他用户的视图时,您只需要获取该用户的信息并将其传递到视图中。无需更改当前用户或完全修改请求。
答案 1 :(得分:1)
您实际上不需要记录当前用户,您只需更改计划用于呈现其他视图的HttpRequest
对象中的用户。你可以这样做:
from django.contrib.auth.models import User
from django.http import HttpResponse
def view_inside_a_view(request):
return HttpResponse('hello %s' % request.user)
def view(request):
# change to dummy user, or whoever
request.user = User.objects.get(id=1)
response = view_inside_a_view(request)
return HttpResponse('rendered view: %s' % response.content)
如果您需要登录虚拟用户,可以使用django.contrib.auth.authenticate
或django.contrib.auth.login
来执行此操作。使用login
的示例(避免使用虚拟用户密码的必要性):
from django.contrib.auth.models import User
from django.contrib.auth import login, get_backends
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
@login_required
def view_inside_a_view(request):
return HttpResponse('hello %s' % request.user)
def view(request):
# login dummy user
user = User.objects.get(id=2)
backend = get_backends()[0]
user.backend = "%s.%s" % (backend.__module__, backend.__class__.__name__)
login(request, user)
# change request's user
request.user = user
# get response from view
response = view_inside_a_view(request)
return HttpResponse('rendered view: %s' % response.content)
答案 2 :(得分:1)
只需使用测试客户端 - 它不仅有助于测试:
from django.test import Client
c = Client()
# login if necessary
c.login(username='dummy', password='user')
# get the view
response = c.get(reverse('my-view', args=[foo,bar])
html = response.content
自1.6以来,这甚至已经正式记录,但它也适用于旧版本:https://docs.djangoproject.com/en/1.6/topics/testing/tools/#module-django.test.client