Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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) 
like image 872
Charles Smith Avatar asked May 04 '17 15:05

Charles Smith


2 Answers

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) 
like image 137
Alasdair Avatar answered Sep 30 '22 08:09

Alasdair


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) 
like image 28
VIctor Angelov Avatar answered Sep 30 '22 08:09

VIctor Angelov