开发者

Creating a fake request to render a view to a string in django

开发者 https://www.devze.com 2023-04-01 10:52 出处:网络
Problem I\'d like to render an arbitrary view, by calling the view (capture the response and extract the rendered content), to a string, inside another view.

Problem

I'd like to render an arbitrary view, by calling the view (capture the response and extract the rendered content), to a string, inside another view. The problem being I'd like to have a dummy user "logged-in" during the rendering of that view, along with changing a few other minor things in the request. What I'd like to avoid is building a request completely from scratch, as 90% of the request I'll have at hand in the parent view will be the same.

I'm wondering how I should go about this as far as best practice is concerned, as well as technically?

I'm currently thinking something like this: (But I can't help but feel this is horrible and there's got to be a better way, I just cannot think of it)

View stuff...

Log current user out

Create/Login dummy user

Somehow modify request a bit

Render view to string

Log out dummy user

Log back in original user

End of view stuff.开发者_Go百科..

Any ideas? Or a pointer into a better direction?

Thanks, dennmat


Depending upon how much you're relying on getting information from the request during the view, it might be best that you just create a function to do all of the view's dirty work, and have your real view just pass in the values it needs into this function. So, instead of a view function that takes a request, create another function that takes a user:

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

Then, when you want to a view using a different user, you only need to grab the information for that user and pass it into the view. No need to change the current user or modify the request at all.


You don't actually need to log the current user out, you could just change the user in the HttpRequest object you plan to use to render the other view. You could do something like this:

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)

If you need to login your dummy user you could use django.contrib.auth.authenticate or or django.contrib.auth.login to do so. Example using login (avoids necessity of using dummy user's password):

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)


just use the test client - it's not only good for testing:

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

Since 1.6 this is even officially documented, however it works in older versions too: https://docs.djangoproject.com/en/1.6/topics/testing/tools/#module-django.test.client

0

精彩评论

暂无评论...
验证码 换一张
取 消