using recaptcha with django's contrib comments module

102 views
Skip to first unread message

Eric St-Jean

unread,
Jun 23, 2007, 12:20:19 AM6/23/07
to django...@googlegroups.com
Hi,

Short form of my question: i have a custom view which does some work and
then calls django.contrib.comments.views.comments.post_free_comment;
i've customized the templates/comments/free_preview.html, and i would
like my custom view to somehow pass an additional variable to that
template, without having to do the whole form validation and
re-instantiation that post_free_comment does. How?

Very long form, skip if you understand the short form:
I integrated recaptcha[1] into the django.contrib.comments comment form
of a little blog app that i wrote with django (based on the django
website blog app, actually, but with tagging).

So i wanted to keep using most of the code from django.contrib.comments
(view, validation, actual posting, ...) while also using recaptcha.

The hack i came up with to do so with minimal work, was to copy and
customize templates/comments/free_preview.html, incorporating the
recaptcha code into it.

The django.contrib.comments.views.comments.post_free_comment view does
everything i need (except for the captcha) for both previewing and
posting. It's in the preview that i show the captcha, using the
aforementionned template (no unnecessary requests to the recaptcha
servers that way). But then, if it's the actual comment post (not the
for-previewing post), i need to actually check that the user solved it.
No problem: i redirected the /comments/postfree/ view to a custom view.
If it's the previewing step, or if it's the posting step and the user
solved the captcha it just goes
return post_free_comment(request)
which does the rest of the validation, and posts the comment.

My small problem is that at that point, i need to pass a simple variable
to free_preview.html, which is the error code that recaptcha sent us
(such as "the user can't read warped text"), so that the captcha on the
refreshed screen will have error text[2].... the problem is that to
instantiate that template with its form, FreeComment's post_free_comment
view uses a ton of code, and i had to duplicate a lot of it into my own
view:

try:
options, target, security_hash =
request.POST['options'], request.POST['target'], request.POST['gonzo']
except KeyError:
raise Http404, _("One or more of the required fields
wasn't submitted")
content_type_id, object_id = target.split(':') # target is
something like '52:5157'
option_list = options.split(',')
new_data = request.POST.copy()
new_data['content_type_id'] = content_type_id
new_data['object_id'] = object_id
new_data['ip_address'] = request.META['REMOTE_ADDR']
new_data['is_public'] = IS_PUBLIC in option_list
manipulator = PublicFreeCommentManipulator()
return render_to_response('comments/free_preview.html', {
'comment': "",
'comment_form': oldforms.FormWrapper(manipulator,
new_data, None),
'options': options,
'target': target,
'hash': security_hash,
'recaptcha_error': recatpcha_resp_text[1],
}, context_instance=RequestContext(request))

(see http://dpaste.com/hold/12801/ for nicely formatted view)

all of that only to pass an extra var ('recaptcha_error') to the
template... the rest of that code is verbatim from the default view.

after all this rambling, my question is quite simple: after having
validated the captcha, if there was an error with it, i'd prefer to just
call django.contrib.comments.views.comments.post_free_comment so that
*it* bothers itself with refreshing the preview form, rendering my
customized template, and so that i don't duplicate the above code. But
how can i pass some value to the template when i'm not the one
instantiating it? Should i add the error text to the session and have
the template somehow retrieve that? Can a custom templatetag have access
to session data?

It all works; i just want it Pretty, and i'm sure there's a stupid
solution that i'm too newb to see.

thank you for your kind attention...

[1] http://recaptcha.net

[2] See http://recaptcha.net/apidocs/captcha Basically, a little js
function goes to the recaptcha server, which returns a form that gets
inserted into the page (so that happens on the client side). If there
was an error in the previous recaptcha validation, the validation server
will have returned an error code. You add this error code to the url
that the client will use to fetch the captcha again, which will then
contain a nice little message telling the user what he did wrong.

--

Aidas Bendoraitis

unread,
Jun 25, 2007, 6:48:46 AM6/25/07
to django...@googlegroups.com
You can do that by writing a wrapper for the
django.contrib.comments.views.comments.post_free_comment view. It
should take the request as an argument, check the validity of the
captcha, add the additional parameter to the request, call
the post_free_comment passing the request to it, and return its response.

Then you will need the request context processor
"django.core.context_processors.request" to be activated in your
TEMPLATE_CONTEXT_PROCESSORS. You will be able to access the parameter
passed like this: {{ request.custom_parameter }}.

Maybe this is not the nicest solution in the world, but it works.

Regards,
Aidas Bendoraitis aka Archatas

Eric St-Jean

unread,
Jun 25, 2007, 9:58:46 AM6/25/07
to django...@googlegroups.com
Hi,
Aidas Bendoraitis a écrit :

> You can do that by writing a wrapper for the
> django.contrib.comments.views.comments.post_free_comment view. It
> should take the request as an argument, check the validity of the
> captcha, add the additional parameter to the request, call
> the post_free_comment passing the request to it, and return its response.

that, i had done...

> Then you will need the request context processor
> "django.core.context_processors.request" to be activated in your
> TEMPLATE_CONTEXT_PROCESSORS. You will be able to access the parameter
> passed like this: {{ request.custom_parameter }}.

but this is precisely the info i was looking for.

thanks a bunch!

> Maybe this is not the nicest solution in the world, but it works.

--
______________________________
Eric St-Jean e...@wwd.ca


Reply all
Reply to author
Forward
0 new messages