django-simple-captcha icon indicating copy to clipboard operation
django-simple-captcha copied to clipboard

Manually displaying the Captcha field in a template

Open mmuk2 opened this issue 11 years ago • 11 comments

Hi,

I'm a bit of a newbie to django-simple-captcha, but I'm finding it really useful.

I have one question, however. I've set up a django form where I've replaced the {% form.as_ul %} with the actual fields in the template. The form has django-simple-captcha hooked up but I don't know how to write the HTML code for the captcha field in my HTML template (including the dynamically generated value key).

It should be something like this:

captcha

How do I generate the dynamic value key though? Can I just create a random hex key and use that, or is there something else I can use?

thanks in advance, Mark

mmuk2 avatar Mar 05 '13 23:03 mmuk2

You don't really need to create the random code for the captcha, that's all done for you (along with validating the user input) when the form is instantiated and submitted.

You probably just need to render the captcha in your template, like so:

{{ form.captcha }}

(assuming you added a CaptchaField to your form named captcha)

EDIT: typo

mbi avatar Mar 06 '13 16:03 mbi

I'm in a similar boat, I want more control than just {{captcha}}.

What magic do I need to put in between the {{}} below?

<div class="form-group">
    <div class="col-sm-2">
        {{ captcha.the_img }}
    </div>
    <div class="col-sm-6">
        {{ captcha.the_text_box }}
        {{ captcha.any_other_hidden_fields }}
    </div>
</div>
<div class="col-sm-4">
    {% if captcha.required %}<span class="required glyphicon glyphicon-asterisk"></span>{% endif %}
    {% if captcha.help_text %}
    <span class="subtle">{{ captcha.help_text|safe }}</span>
    {% endif %}
    {% for error in captcha.errors %}
    <p class="text-danger">{{ error }}</p>
    {% endfor %}
</div>

Thanks!

kneufeld avatar Aug 07 '14 00:08 kneufeld

I know I can define the output with CAPTCHA_OUTPUT_FORMAT see http://django-simple-captcha.readthedocs.org/en/latest/advanced.html#captcha-output-format but this will set the output for the whole project. This is not flexibel enough for me. Please support more template variables as stated above.

dlgltlzed avatar Apr 02 '15 15:04 dlgltlzed

Totally agree. I have other input fields that are written a certain way, and when I can't control the attributes that make up the captcha tags, it looks really ugly. Something like this would be nice:

<img src="{% url 'captcha-image' form.captcha.img_key %}">
{{ form.captcha.hidden_fields }}
<input type="text" name="captcha_1" some="other" attributes>

takeshibaconsuzuki avatar Sep 15 '15 22:09 takeshibaconsuzuki

It seems that django-simple-captcha hard code the img tag

    def render(self, name, value, attrs=None):
        self.fetch_captcha_store(name, value, attrs)

        self.image_and_audio = '<img src="%s" alt="captcha" class="captcha" />' % self.image_url()
        if settings.CAPTCHA_FLITE_PATH:
            self.image_and_audio = '<a href="%s" title="%s">%s</a>' % (self.audio_url(), ugettext('Play CAPTCHA as audio file'), self.image_and_audio)
        return super(CaptchaTextInput, self).render(name, self._value, attrs=attrs)

This is my solution, to control the attributes we can search the hashkey, then we can render our custom img tag:

views.py

form = forms.RegisterForm()
captcha_hash = re.search('\w{40}', form['captcha'].__str__()).group()
return render(request, "login.html", locals())

login.html

                    <div class="form-group">
                        <div class="col-lg-offset-2 col-lg-6">
                            <input type="text" autocomplete="off" id="id_captcha_1" name="captcha_1" class="form-control" placeholder="validate code">
                        </div>
                        <div class="col-lg-2">
                            <img class="form-control" src="/user/captcha/image/{{ captcha_hash }}" />
                            <input id="id_captcha_0" name="captcha_0" type="hidden" value="{{ captcha_hash }}" />
                        </div>
                    </div>

zt2 avatar Oct 22 '15 08:10 zt2

@zt2 offloading the rendering of the whole field to Django's template rendering mechanism is a pretty good idea, especially because the template can be easily overridden.

I'll definitely take a look at that, my only concern is to produce a backward-compatible solution.

mbi avatar Oct 22 '15 08:10 mbi

@zt2 your solution works for me (at least for now). Thanks!

takeshibaconsuzuki avatar Nov 02 '15 05:11 takeshibaconsuzuki

Ok this is now implemented, you can render both the individual components (image, hidden input, text input) as well as the "assembled" elements using Django templates.

I'd really appreciate if you could check out the template-rendering branch and give it a test before I merge it.

Edit: WIP documentation is here.

mbi avatar Nov 02 '15 10:11 mbi

I couldn't get this to work, nor could I install 0.4.7. Even just using the default {{ captcha }} in the form template just creates an input box with no image. The docs don't discuss rendering AT ALL.

ursomniac avatar Nov 24 '15 13:11 ursomniac

@ursomniac try this:

pip install -e git+https://github.com/mbi/django-simple-captcha.git#egg=captcha-dev

There is a link to the WIP documentation that does discuss rendering right here.

mbi avatar Nov 24 '15 13:11 mbi

Custom widget templates introduced by Django 1.11 are enabled in #139.

ziima avatar Apr 05 '18 10:04 ziima