2012-06-06 28 views
5

Necesito hacer una clase de formulario que puede o no tener un campo ReCaptcha dependiendo de si el usuario está conectado o no.Campo condicional en el formulario

Como se trata de un CommentForm, no tengo acceso al objeto request en la creación/definición del formulario, por lo que no puedo confiar en eso.

Para la solicitud POST la solución es fácil: Tengo esto:

class ReCaptchaCommentForm(CommentForm): 
    def __init__(self, data=None, *args, **kwargs): 
     super(ReCaptchaCommentForm, self).__init__(data, *args, **kwargs) 
     if data and 'recaptcha_challenge_field' in data: 
      self.fields['captcha'] = ReCaptchaField() 

Una vez hecho esto, la validación de formularios debe funcionar según lo previsto. El problema ahora está en el lado de la plantilla. Necesito la plantilla que ser así:

<form action={% comment_form_target %} method="post"> 
{# usual form stuff #} 
{% if not user.is_authenticated %} 
<script type="text/javascript" 
     src="http://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script> 
<div id="recaptcha-div"></div> 
<script type="text/javascript"> 
    Recaptcha.create({{ public_key }}, "recaptcha-div", 
        { theme: 'white', 
        callback: Recaptcha.focus_response_field }); 
</script> 
{% endif %} 
</form> 

pero me gustaría no tener que repetir ese código en cada plantilla comments/*/form.html. Supongo que debería haber alguna manera de agregar un código equivalente desde el método render de un widget y la definición Media.

¿Alguien puede pensar en una buena manera de hacer esto?

+1

El problema es que los widgets no saben nada acerca de la solicitud, por lo que no hay forma de representar condicionalmente en función del usuario que ha iniciado sesión. Aunque, es posible que desee ver django-floppyforms. Como utiliza plantillas para representar widgets, es posible que pueda hacer lo que quiera de esa manera. –

+0

sí, esa es la idea que tuve, renderizar un widget a través de una plantilla. Pero no estoy seguro de poder tener request.user en mi template vars incluso si hago esto (widget.render puede hacer lo que quiera, incluyendo renderizar una plantilla, el contexto es el problema). Lo que me gustaría hacer es renderizar una plantilla, que será analizada más tarde en – Lacrymology

+1

Es por eso que sugerí django-floppyforms. No estoy del todo seguro, pero creo que funciona con el patrón de inclusión estándar, en lugar de simplemente hacer que 'render' use una plantilla. Debería tener acceso a 'request' en el contexto de la plantilla al igual que cualquier otra plantilla incluida.Pruébelo y vea. –

Respuesta

4

que suponer que usted instatiate su formulario en una vista, por lo que sólo podía pasar al usuario desde la solicitud hasta la forma (al igual que en aplicación de autenticación SetPassword formulario):

def __init__(self, user, data=None, *args, **kwargs): 
    super(ReCaptchaCommentForm, self).__init__(data, *args, **kwargs) 
    if user.is_authenticated(): 
     self.fields['captcha'] = ReCaptchaField() 
+0

no, el sistema de comentarios no funciona así (no es una vista, es una plantilla, y no pasa la solicitud (O el usuario) como parámetro. Esto es parte de la descripción! – Lacrymology

0

Bueno, es una pena que django-floppyforms no dé acceso a la solicitud. Hubiera sido bueno saber que era una opción, ya que recientemente comencé a usar django-floppyforms en mi propio proyecto.

A falta de eso, lo mejor que puedo pensar es simplemente confiar en la herencia de la plantilla. Puede crear un archivo comments/form.html y luego hacer que cada comments/*/form.html amplíe eso. Coloque el código Recaptcha tal como lo tiene en la base form.html y listo.

+0

eso es lo que hice, pero me gustaría una solución más agradable. Especialmente desde a) Tendré que hacer lo mismo para formularios fuera del sistema de comentarios, yb) esto debería ser trivial – Lacrymology

+0

Bueno, es como * is * trivial. Solo tiene que agregar la secuencia de comandos a una plantilla base de la que todas las formas heredan. Y, si lo necesita fuera del sistema de comentarios, no hay nada que diga que no puede tener una plantilla form.html de nivel aún mayor, tal vez de inmediato en el directorio principal de plantillas, que esta aplicación y todas las demás aplicaciones que la necesitan hereden de . –

3

Uso crispy-forms! Puede incluir elementos html en el diseño del formulario que le permita excluir/incluir un campo según el contexto de solicitud de vistas. Funciones extremadamente útiles fuera de eso también.

Here's the relevant doc section.

+0

oh, yo Volveré a esta tarea después de haber arreglado algunas otras cosas. De hecho, ya estoy incluyendo formas crujientes pero aún no las he usado, ya que utilizamos un método más basado en plantillas. – Lacrymology

0

Lo que estoy haciendo sobre campos condicionales es tener una clase base (que hereda de Form) y otras subclases con los campos condicionales adicionales.

En mi opinión, dependiendo de la condición, elijo la forma subclasificada requerida. Sé que implica algún código duplicado, pero parece más fácil que otros enfoques.

Cuestiones relacionadas