Django 1.11 TypeError context must be a dict rather than Context

Just received the Sentry error TypeError context must be a dict rather than Context. on one of my forms. I know it has something to do with Django 1.11, but I am not sure what to change to fix it.

Offending line

message = get_template('email_forms/direct_donation_form_email.html').render(Context(ctx))

Entire View

def donation_application(request):
    if request.method == 'POST':
        form = DirectDonationForm(data=request.POST)
        if form.is_valid():
            stripe.api_key = settings.STRIPE_SECRET_KEY
            name = request.POST.get('name', '')
            address = request.POST.get('address', '')
            city = request.POST.get('city', '')
            state = request.POST.get('state', '')
            zip = request.POST.get('zip', '')
            phone_number = request.POST.get('phone_number', '')
            support = request.POST.get('support', '')
            agree = request.POST.get('agree', '')
            email_address = request.POST.get('email_address', '')
            number = request.POST.get('number', '')
            cvc = request.POST.get('cvc', '')
            exp = request.POST.get('exp', '')
            # token = form.cleaned_data['stripe_token'],
            # exp_m = int(request.POST.get('exp_month', ''))
            # exp_y = int(request.POST.get('exp_year', ''))

            exp_month = exp[0:2]
            exp_year = exp[5:9]

            subject = 'New Donation'
            from_email = settings.DEFAULT_FROM_EMAIL
            recipient_list = ['deniselarkins@/////\\\\\.com',
                              'charles@/////\\\\\.net',
                              'marcmunic@/////\\\\\.com',
                              ]

            token = stripe.Token.create(
                card={
                    'number': number,
                    'exp_month': exp_month,
                    'exp_year': exp_year,
                    'cvc': cvc
                },
            )

            customer = stripe.Customer.create(
                email=email_address,
                source=token,
            )

            total_support = decimal.Decimal(support) / 100
            total_charge = decimal.Decimal(int(support)) / 100

            # Charge the user's card:
            charge = stripe.Charge.create(
                amount=total_charge,
                currency='usd',
                description='Donation',
                customer=customer.id
            )

            ctx = {
                'name': name,
                'address': address,
                'city': city,
                'state': state,
                'zip': zip,
                'phone_number': phone_number,
                'email_address': email_address,
                'agree': agree,
                'charge': charge,
                'customer': customer,
                'total_support': total_support,
                'total_charge': total_charge
            }

            message = get_template('email_forms/direct_donation_form_email.html').render(Context(ctx))
            msg = EmailMessage(subject, message, from_email=from_email, to=recipient_list)
            msg.content_subtype = 'html'
            msg.send(fail_silently=True)

            return redirect(
                '/contribute/donation-support-thank-you/?name=' + name +
                '&address=' + address +
                '&state=' + state +
                '&city=' + city +
                '&zip=' + zip +
                '&phone_number=' + phone_number +
                '&email_address=' + email_address +
                '&total_support=' + str(total_support) +
                '&total_charge=' + str(total_charge)
            )
    context = {
        'title': 'Donation Pledge',
    }

    return render(request, 'contribute/_donation-application.html', context)

In Django 1.8+, the template's render method takes a dictionary for the context parameter. Support for passing a Context instance is deprecated, and gives an error in Django 1.10+.

In your case, just use a regular dict instead of a Context instance:

message = get_template('email_forms/direct_donation_form_email.html').render(ctx)

You may prefer to use the render_to_string shortcut:

from django.template.loader import render_to_string

message = render_to_string('email_forms/direct_donation_form_email.html', ctx)

If you were using RequestContext instead of Context, then you would pass the request to these methods as well so that the context processors run.

message = get_template('email_forms/direct_donation_form_email.html').render(ctx, request=request)
message = render_to_string('email_forms/direct_donation_form_email.html', ctx, request=request)

Migrated from Django 1.8 to Django 1.11.6

Wherever i had a RequestContext class, there is a method flatten() wich return the result as a dict.

So if the class is RequestContext....

return t.render(context)

becomes

return t.render(context.flatten())

And in a case wich the context is is wrapped by Context(), just remove it. Because Context() is deprecated.

return t.render(Context(ctx))

becomes

return t.render(ctx)

For django 1.11 and after, context must be dict.

You can use:

context_dict = get_context_dict(context)
return t.render(context_dict)

or

context_dict = context.flatten()
return t.render(context_dict)