*e.g. filecaptcha.py:* CAPTCHA_SOLUTIONS = {'01.png': ['alfa romeo', 'alfa-romeo', 'alfaromeo'], '02.png': ['audi'], ... --- *urls.py:* extra_context = {'contact_form': MessageForm(), 'captcha_choices': CAPTCHA_SOLUTIONS.keys()} --- *forms.py:* class MessageForm(forms.Form): captcha = forms.CharField(label='Spam protection') captcha_img = forms.CharField(required=False) def clean(self): if not self.data['captcha']: raise forms.ValidationError('This field is required.') if self.data['captcha'].lower() in CAPTCHA_SOLUTIONS.get(self.data['captcha_img']): return self.cleaned_data raise forms.ValidationError('Wrong solution') --- *base.html:* {% if contact_form %} {% with captcha=captcha_choices|random %} {% if contact_form.non_field_errors %} {{contact_form.non_field_errors}} {% endif %} captcha {% endwith %} {% endif %} --- *views.py (contact_form POST target):* form = MessageForm(request.POST or None) if form.is_valid(): #save and redirect return render_to_response('contact.html', {'form': form, 'captcha': random.choice(CAPTCHA_SOLUTIONS.keys()), }, context_instance=RequestContext(request))