example · django

03 / 06

Django spam filter.

Updated May 12, 2026

This Django example wires Siftfy spam detection into a `require_POST` contact view. The view sends the submitted message to `https://api.siftfy.io/v1/predict`, drops submissions scored above the response's own `max_confidence`, queues everything from 0.50 up to that ceiling for moderation, and delivers the rest. It uses a 2-second timeout and fails open so request exceptions never break the form.

A Django view that scores a submitted message with Siftfy before sending email or queuing moderation.

python
# pip install requests
import os
import requests
from django.http import JsonResponse
from django.views.decorators.http import require_POST

@require_POST
def contact(request):
    email = request.POST.get("email", "")
    message = request.POST.get("message", "")
    if not email or not message:
        return JsonResponse({"error": "email and message required"}, status=400)

    probability, ceiling = 0.0, None
    try:
        resp = requests.post(
            "https://api.siftfy.io/v1/predict",
            headers={"X-API-Key": os.environ["SIFTFY_KEY"]},
            json={"text": message},
            timeout=2,
        )
        if resp.ok:
            body = resp.json()
            probability, ceiling = body["spam_probability"], body.get("max_confidence")
    except requests.RequestException:
        probability = 0.0

    # Drop only ABOVE the ceiling the response reports. At the ceiling the score
    # is censored, so a fixed constant never fires on the model's own opinion.
    if ceiling is not None and probability > ceiling:
        return JsonResponse({"ok": True})
    if probability >= 0.50:
        queue_for_review(email=email, message=message, probability=probability)
    else:
        deliver_to_inbox(email=email, message=message)
    return JsonResponse({"ok": True})

Production notes

  1. 01`max_confidence` is the highest score the model is allowed to return on its own word; only a score above it is more than the model's opinion.
  2. 02For async Django views, use httpx.AsyncClient and the same thresholds.
  3. 03Do not return a spam-specific error to the browser.
  4. 04Store probability and action for audits, not the full body unless your privacy policy allows it.

Common questions

How do I integrate Siftfy spam detection with Django?

POST the form's `message` field to `https://api.siftfy.io/v1/predict` from inside a Django view, then branch on the returned `spam_probability`. Use `requests` for sync views or `httpx.AsyncClient` for async views. The full view is shown above.

Where should the Siftfy API key live in a Django project?

Read it from an environment variable via `os.environ['SIFTFY_KEY']` or `django-environ` and reference it from `settings.py`. Never commit the key to source control.

How do I avoid blocking the request thread on Siftfy calls?

Use Django 4.1+ async views with `httpx.AsyncClient`, or move the call into a background task with Celery / Django-Q when latency budget is tight. Keep the timeout under 2 seconds either way.

Should Django log full message bodies for spam audits?

Log the probability, the action you took, and request metadata, but avoid logging full message bodies unless your privacy policy permits it. Truncated previews are usually enough for false-positive review.

Get a free API key

More patterns: all examples, contact forms, API reference.