raven-python icon indicating copy to clipboard operation
raven-python copied to clipboard

[DOCS] Django Integration for User Feedback

Open audiolion opened this issue 8 years ago • 6 comments

The docs for user feedback integration with Django state that it is as simple as dropping that into the 500.html template. However, this is incorrect.

Django's default server_error() view passes an empty context variable so the template renders and the {% if request.sentry.id %} line always results in False because there is no request object passed back (empty context dict).

The resolution is stated in the docs where it references a custom handler500() view that passes the context. I feel like that needs to be included down in the User Feedback section somewhere, and can submit a PR if you'd like.

The new documentation for User Feedback would look something like:

User Feedback

By default Django will render 500.html, so simply drop the following snippet into your template:

<!-- Sentry JS SDK 2.1.+ required -->
<script src="https://cdn.ravenjs.com/2.3.0/raven.min.js"></script>

{% if request.sentry.id %}
  <script>
  Raven.showReportDialog({
    eventId: '{{ request.sentry.id }}',

    // use the public DSN (dont include your secret!)
    dsn: '___PUBLIC_DSN___'
  });
  </script>
{% endif %}

Then override the default 500 handler to include the context information. In your URL Conf (base urls.py) add:

handler500 = 'myapp.views.sentry_server_error'

Then define that view as:

from django import http
from django.template import Context, RequestContext, TemplateDoesNotExist, loader
from django.views.decorators.csrf import requires_csrf_token


@requires_csrf_token
def sentry_server_error(request, template_name='500.html'):
    try:
        template = loader.get_template(template_name)
    except TemplateDoesNotExist:
        return http.HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
    return http.HttpResponseServerError(template.render(RequestContext(request)))

Note

Because Django's default server_error() passes an empty context variable we need to create a custom 500 error handler to pass the request context.

audiolion avatar Jan 25 '17 18:01 audiolion

I suppose we could do provide a built-in replacement to server_error which handles passing in the required context from Sentry. There's good reasons you don't want context in general to be available, but we can guarantee safety around things we provide.

dcramer avatar Jan 29 '17 00:01 dcramer

In django >= 2.0

@requires_csrf_token
def sentry_server_error(request, template_name=ERROR_500_TEMPLATE_NAME):
    """
    500 error handler.

    Templates: :template:`500.html`
    Context: None
    """
    try:
        template = loader.get_template(template_name)
    except TemplateDoesNotExist:
        if template_name != ERROR_500_TEMPLATE_NAME:
            # Reraise if it's a missing custom template.
            raise
        return HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
    #return HttpResponseServerError(template.render(RequestContext(request))) # instead of this; to avoid TypeError
    return HttpResponseServerError(template.render(context=None, request=request))

jaaved avatar May 08 '18 15:05 jaaved

@dcramer,

FYI, I just ran into this as well. The docs don't mention using a custom 500 view right now either.

epicserve avatar Oct 02 '18 21:10 epicserve

I guess It does say something in the Message Reference section, but I missed it because there wasn't anything in the User Feedback Section.

https://docs.sentry.io/clients/python/integrations/django/#message-references

epicserve avatar Oct 02 '18 21:10 epicserve

Also as an FYI you might want to suggest a server error view like the following so you can dynamically insert the dsn.

from urllib.parse import urlparse

def server_error(request):

    # Use the 500 template for each program if it exists
    url_segment = request.path_info.strip("/").split("/")
    program_500_template = "%s/500.html" % url_segment[0]
    t = loader.select_template([program_500_template, '500.html'])

    sentry_dsn = None
    if hasattr(settings, 'RAVEN_CONFIG') is True and 'dsn' in settings.RAVEN_CONFIG and settings.RAVEN_CONFIG['dsn']:
        # strip out the password
        url_obj = urlparse(settings.RAVEN_CONFIG['dsn'])
        sentry_dsn = '{scheme}://{username}@{hostname}{path}'.format(scheme=url_obj.scheme, username=url_obj.username, hostname=url_obj.hostname, path=url_obj.path)

    context_dict = {'request': request, 'sentry_dsn': sentry_dsn}
    return HttpResponseServerError(t.render(context_dict))

epicserve avatar Oct 02 '18 22:10 epicserve

I also came across this error today. I was following the docs here and inconveniently it doesn't mention the step of overriding the 500 handler. If you follow that as shown in the top answer and then the rest of the code in the docs will help solve the problem.

AzyCrw4282 avatar Nov 12 '21 16:11 AzyCrw4282