Integrations · Updated 2026-10-20

Signup checks in Django

Validate signups in a Django form's clean() method, including the client IP behind a proxy and a fail-open timeout.

A helper

# accounts/veqen.py
import os
import requests


def screen_signup(email, ip=None, phone=None):
    try:
        response = requests.post(
            "https://veqen-app.com/v1/signup/check",
            headers={"Authorization": f"Bearer {os.environ['VEQEN_API_KEY']}"},
            json={"email": email, "ip": ip, "phone": phone},
            timeout=4,
        )
        response.raise_for_status()
        return response.json()
    except requests.RequestException:
        return None  # fail open


def client_ip(request):
    forwarded = request.META.get("HTTP_X_FORWARDED_FOR")
    if forwarded:  # only trust this header if your proxy sets it
        return forwarded.split(",")[0].strip()
    return request.META.get("REMOTE_ADDR")

In the form

# accounts/forms.py
from django import forms
from .veqen import client_ip, screen_signup


class SignupForm(forms.Form):
    email = forms.EmailField()
    password = forms.CharField(widget=forms.PasswordInput, min_length=10)

    def __init__(self, *args, request=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
        self.veqen = None

    def clean_email(self):
        email = self.cleaned_data["email"]
        self.veqen = screen_signup(email, ip=client_ip(self.request))
        if self.veqen:
            suggestion = self.veqen["email"].get("did_you_mean")
            if suggestion:
                raise forms.ValidationError(f"Did you mean {suggestion}?")
            if self.veqen["risk"]["verdict"] == "refuse":
                raise forms.ValidationError("Please use a permanent email address.")
        return email
# accounts/views.py
def signup(request):
    form = SignupForm(request.POST or None, request=request)
    if request.method == "POST" and form.is_valid():
        verdict = form.veqen["risk"]["verdict"] if form.veqen else "review"
        user = create_user(form.cleaned_data, needs_verification=(verdict == "review"))
        return redirect("onboarding")
    return render(request, "signup.html", {"form": form})