Abu bakr
Abu bakr

Reputation: 79

Django TypeError: render() takes 2 positional arguments but 3 were given?

I am sending an email to my drivers from my employee site but I am not able to send a driver id with the url link. I get the error:

join_message = template.render(ctx, request)**
TypeError: render() takes 2 positional arguments but 3 were given**

My view:

def rentacar_carapp_approve(request):
    if request.POST:
        try:
            args['driver'] = driver = Driver.objects.get(id=request.POST.get('driver_id'))
            subject = "Please Register Your Car"
            from_email = settings.EMAIL_HOST_USER
            to_email = '[email protected]'
            if to_email is not None:
                template = Template("""Please hit the link and book a car {{ request.get_host }}{% url 'detail' driver_id=driver_id %}""")
                ctx = Context({'driver_id': driver.id})
                join_message = template.render(ctx, request)
                send_mail(subject=subject, from_email=from_email, recipient_list=[to_email], message=join_message,
                          fail_silently=False)
                print("email sent")
        except Driver.DoesNotExist:
            print("Driver doesn't exists")
        return HttpResponseRedirect('/mega-admin/rentacar/carapp-manager/')

Upvotes: 1

Views: 3622

Answers (3)

Sina Khelil
Sina Khelil

Reputation: 1991

First, You need to remove request from join_message = template.render(ctx, request) and use join_message = template.render(ctx)

see docs

then build it properly:

template = Template("""Please hit the link and book a car {{ booking_link }}""")
ctx = Context({'booking_link': request.build_absolute_uri(reverse('detail', kwargs={'driver_id': driver_id}))})
join_message = template.render(ctx)

build_absolute_uri docs

reverse docs

I did not test it, but it should return what you are looking for...

Upvotes: 1

Alasdair
Alasdair

Reputation: 309109

To pass the request to the template context you can either explicitly include it in the context:

template = Template("""Please hit the link and book a car {{ request.get_host }}{% url 'detail' driver_id=driver_id %}""")
ctx = Context({'driver_id': driver.id, 'request': request})
join_message = template.render(ctx, request)

Or you can use RequestContext (assuming you have the request context processor enabled.

template = Template("""Please hit the link and book a car {{ request.get_host }}{% url 'detail' driver_id=driver_id %}""")
ctx = RequestContext(request, {'driver_id': driver.id})
join_message = template.render(ctx, request)

Note that it's unusual to instantiate templates from strings (e.g. template = Template("""...""")). Usually, you would save the template to a file in your templates directory (e.g. car_approve.email), then use the render_to_string shortcut to render the template. The render_to_string template does accept request as an argument.

from django.template.loader import render_to_string
context = {'driver_id': driver.id}
join_message = render_to_string('car_approve.email', context, request=request)

Upvotes: 2

bdribault
bdribault

Reputation: 91

You should not give the request parameter.

https://docs.djangoproject.com/en/2.1/ref/templates/api/#django.template.Template

To explain the error message, you are giving 2 arguments to the render method, which is bound to a template insance. This "function" actually receive 3 parameters, the first one being "self" (your Template instance).

Upvotes: 2

Related Questions