Acabo de recibir el error Sentry TypeError context must be a dict rather than Context. en uno de mis formularios. Sé que tiene algo que ver con Django 1.11, pero no estoy seguro de qué cambiar para solucionarlo.
línea ofensiva
message = get_template('email_forms/direct_donation_form_email.html').render(Context(ctx))
Vista completa
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)En Django 1.8+ , el método de render de la plantilla toma un diccionario para el parámetro de context . El soporte para pasar una instancia de Context está en desuso y da un error en Django 1.10+.
En su caso, simplemente use un dict regular en lugar de una instancia de Context :
message = get_template('email_forms/direct_donation_form_email.html').render(ctx) Es posible que prefiera usar el atajo render_to_string :
from django.template.loader import render_to_string message = render_to_string('email_forms/direct_donation_form_email.html', ctx) Si estuviera usando RequestContext en lugar de Context , también pasaría la request a estos métodos para que se ejecuten los procesadores de contexto.
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)Migrado de Django 1.8 a Django 1.11.6
Dondequiera que tuviera una clase RequestContext, hay un método flatten() que devuelve el resultado como un dictado.
Entonces, si la clase es RequestContext....
return t.render(context)se convierte
return t.render(context.flatten())Y en caso de que el contexto esté envuelto por Context(), simplemente elimínelo. Porque Context() está en desuso.
return t.render(Context(ctx))se convierte
return t.render(ctx)Para Django 1.11 y posteriores, el contexto debe ser dict.
Puedes usar:
context_dict = get_context_dict(context) return t.render(context_dict)o
context_dict = context.flatten() return t.render(context_dict)Llegué aquí porque tenía el mismo problema. Estoy aprendiendo Django con Django Unleashed de Andrew Pinkham. Es un libro de 2015.
Encontré en la documentación oficial que se debe pasar un diccionario al parámetro de contexto y no una instancia de Contexto (de django.template.Context).
@Alasdair sugirió usar render_to_string, pero, al menos en Django 3.2, el método render usa el método render_to_string intrínsecamente.
def render(request, template_name, context=None, content_type=None, status=None, using=None): """ Return a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed arguments. """ content = loader.render_to_string(template_name, context, request, using=using) return HttpResponse(content, content_type, status)entonces, usar solo el método de renderizado podría ser mejor. Proporciono esta respuesta porque era la que estaba buscando y puede ayudar a alguien a llegar a esta pregunta de desbordamiento de pila.