cómo obtener datos POST en django 1.3

Oye, estoy siguiendo este tutorial para aprender a hacer una página wiki con Django. Sin embargo, está hecho en django 0.96 y yo uso Django 1.3, por lo que hay algunas cosas que son diferentes. Algunos ya los arreglé yo mismo, sin embargo, este parece que no puedo hacerlo funcionar.

Hice un formulario que envía datos a una vista. Esta es la forma:

<form method="post" action"/wikicamp/{{page_name}}/save/">{% csrf_token %}
    <textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
    <input type="submit" value="Save Page"/>
</form>

y / wikicamp / {{page_name}} / save / url redirecciona a la vista save_page:

from django.http import HttpResponseRedirect
from django.core.context_processors import csrf

def save_page(request, page_name):
    c = {}
    c.update(csrf(request))
    content = c.POST["content"]
    try:
        page = Page.objects.get(pk=page_name)
        page.content = content
    except Page.DoesNotExist:
        page = Page(name=page_name, content=content)
    page.save()
    return HttpResponseRedirect("wikicamp/" + page_name + "/")

Sin embargo, el problema es que obtengo este error:

Help

Reason given for failure:

    CSRF token missing or incorrect.


In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django's CSRF mechanism has not been used correctly. For POST forms, you need to ensure:

    The view function uses RequestContext for the template, instead of Context.
    In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL.
    If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data.

You're seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed.

You can customize this page using the CSRF_FAILURE_VIEW setting.

Así que leí parte de la documentación, como http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-to-use-it. Sin embargo, intenté hacer eso y todavía me dio el mismo error.

Entonces: ¿Alguien tiene una idea de cómo manejar bien los datos de publicación de formularios con Django 1.3?

Creo que tiene algo que ver con: la función de vista usa RequestContext para la plantilla, en lugar de Context. pero ahora no sé lo que es.

Por cierto, en mi terminal que muestra la solicitud http del localhost dice esto: Se usó un {% csrf_token%} en una plantilla, pero el contexto no proporcionó el valor. Esto generalmente se debe a que no se usa RequestContext.

preguntado el 16 de mayo de 11 a las 17:05

4 Respuestas

Necesitará la etiqueta de plantilla {% csrf_token%} entre sus etiquetas, además de incluir

   django.middleware.csrf.CsrfViewMiddleware
   django.middleware.csrf.CsrfResponseMiddleware

en sus MIDDLEWARE_CLASSES en la configuración de las aplicaciones.py

Añadiendo un ejemplo de manejo de datos de publicaciones:

Este es un ejemplo de una de las veces que estoy usando datos POST en una vista. Por lo general, confiaré en la clase de formulario para realizar la verificación a través de la matriz clean_data.

if request.method == 'POST':
        form = ForgotPassword(data=request.POST)
        if form.is_valid():
            try:
                new_user = backend.forgot_password(request, **form.cleaned_data)
            except IntegrityError:
                context = {'form':form}
                form._errors[''] = ErrorList(['It appears you have already requested a password reset, please \
                check ' + request.POST['email2'] + ' for the reset link.'])
                return render_template(request,'passwordReset/forgot_password.html',context)
            if success_url is None:
                to, args, kwargs = backend.post_forgot_password(request, new_user)
                return redirect(to, *args, **kwargs)
            else:
                return redirect(success_url)

contestado el 16 de mayo de 11 a las 22:05

si agrego ese y hago clic en el botón de formulario, no se produce ningún error, pero la página del formulario simplemente se recarga vaciando el campo de área de texto mientras no sucede nada. (no es la redirección que quiero de todos modos) - Javaaaa

Actualicé mi vista en la pregunta con c.update (csrf (request)) content = c.POST ["content"], ¿es esa la forma correcta de hacerlo? - Javaaaa

¿Está activada la depuración? si es así, ¿puede publicar el seguimiento de la pila? - Grantk

No creo que necesariamente tenga que usar el token, me encontré con esto hace unos meses al actualizar de 1.1 a 1.3 y todo lo que tuve que hacer fue agregar las entradas de middleware y el csrf_token - Grantk

Actualicé mi pregunta con todo el error. Si esto no es un seguimiento de pila, explíqueme cómo puedo obtenerlo. ¡Gracias! - Javaaaa

Tienes que incluir {% csrf_token %} en la plantilla de su formulario entre su <form> las etiquetas.

<form method="post" action"/wikicamp/{{page_name}}/save/">
    {% csrf_token %}
    <textarea name="content" rows="20" cols="60">{{content}}</textarea><br>
    <input type="submit" value="Save Page"/>
</form>

Si la línea csrf_token no se procesa en su formulario, asegúrese de proporcionar el RequestContext en la respuesta de la vista:

from django.shortcuts import render_to_response
from django.template import RequestContext

def app_view(request):
    return render_to_response('app_template.html', 
                              app_data_dictionary, 
                              context_instance=RequestContext(request))

O utilice este método de acceso directo:

from django.views.generic.simple import direct_to_template

def app_view(request):             
    return direct_to_template(request, 'app_template.html', app_data_dictionary)

La RequestContext siempre está disponible cuando utiliza vistas genéricas.

contestado el 17 de mayo de 11 a las 16:05

eso no funciona, ya lo hice antes de preguntar por aquí. Hice las cosas descritas en el último enlace de los documentos. ¿Alguna idea? - Javaaaa

¿Recargaste la página antes de volver a enviarla? Puede ver la fuente para verificar que el token CSRF realmente se representa en el formulario. - peterpillar

Echando un vistazo más de cerca, ¿tienes django.middleware.csrf.CsrfViewMiddleware en su MIDDLEWARE_CLASSES in settings.py? - peterpillar

sí, lo hice, el token csrf no se representa en el formulario. Pero, ¿cómo podría la inclusión de ese token resolver todos mis problemas con CSRF? - Javaaaa

También puede intentar eliminar sus cookies. - peterpillar

Supongo que te has perdido el símbolo '=' en la declaración del formulario.

action"/wikicamp/{{page_name}}/save/"

action="/es/wikicamp/{{page_name}}/save/"

Afortunadamente, puede que no sea un error. Entonces, si no es una solución, pruebe con un ejemplo más sencillo:

# settings.py

TEMPLATE_DIRS = (
    # Here comes something like "C:/www/django/templates"
)

MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.csrf.CsrfViewMiddleware',
    ...
)

# urls.py

urlpatterns = patterns('',
    ('^foo', foo),
)


# views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.core.context_processors import csrf

def foo(request):
    d = {}
    d.update(csrf(request))
    if 'output' in request.POST:
        d.update({'output':request.POST['output']})
    return render_to_response('foo.html',d)

# foo.html template
<html>
<h1> Foo </h1>
<form action="/es/foo" method = "post">
    {% csrf_token %}
    <input type="text" name="output"></input>
    <input type="submit" value="go"></input>
</form>
<p> Output: {{ output }} </p>
</html>

Espero que esto funcione

contestado el 17 de mayo de 11 a las 11:05

re arriba use "request.POST" no "c.POST" en la tercera línea

def save_page (request,page_name):
    content = request.POST["content"]

y cambiar en "edit_page"

-   return render_to_response("edit.html",{"page_name":page_name, "content":content})
+   t = get_template('edit.html')
+   html = t.render(Context({"page_name":page_name, "content":content}))
+   return HttpResponse(html)

- :remove 
+ :add

Respondido 10 ago 11, 21:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.