mbi / django-simple-captcha

Django Simple Captcha is an extremely simple, yet highly customizable Django application to add captcha images to any Django form.
http://django-simple-captcha.readthedocs.io/en/latest/
MIT License
1.38k stars 320 forks source link

Manually displaying the Captcha field in a template #31

Open mmuk2 opened 11 years ago

mmuk2 commented 11 years ago

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

mbi commented 11 years ago

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

kneufeld commented 10 years ago

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!

dlgltlzed commented 9 years ago

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.

takeshibaconsuzuki commented 9 years ago

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>
zt2 commented 8 years ago

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>
mbi commented 8 years ago

@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.

takeshibaconsuzuki commented 8 years ago

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

mbi commented 8 years ago

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.

ursomniac commented 8 years ago

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.

mbi commented 8 years ago

@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.

ziima commented 6 years ago

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