как получить данные POST в Django 1,3 - PullRequest
9 голосов
/ 16 мая 2011

Эй, я следую этому уроку, чтобы научиться делать вики-страницу с Django.Тем не менее, это сделано в Django 0,96, и я использую Django 1,3, поэтому есть некоторые вещи, которые отличаются.Кое-что я уже исправил сам, однако этот, который я не могу заставить его работать.

Я создал форму, которая передает данные в представление.Это форма:

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

и / wikicamp / {{page_name}} / save / url перенаправляет в представление 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 + "/")

Однако проблема в том, что я получаюэта ошибка:

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.

Так что я прочитал некоторые документы, например http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#how-to-use-it. Я попытался сделать это, однако, и это все равно выдало ту же ошибку.

Итак: у кого-нибудь есть идея, как правильно обрабатывать данные постов в Django 1.3?

Я думаю, что это как-то связано с: Функция представления использует RequestContext для шаблона, а не Context.но я не знаю, что это такое.

Кстати, в моем терминале, который показывает http-запрос localhost, он говорит следующее: {% csrf_token%} был использован в шаблоне, но контекст не сделалпредоставить значение.Обычно это вызвано тем, что не используется RequestContext.

Ответы [ 4 ]

9 голосов
/ 16 мая 2011

Вам понадобится тег шаблона {% csrf_token%} между вашими тегами, включая

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

в вашем MIDDLEWARE_CLASSES в приложениях settings.py

Добавление некоторого примера обработки данных после публикации:

Это пример одного из случаев, когда я использую данные POST в представлении. Обычно я буду полагаться на класс формы для проверки через массив cleaned_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)
9 голосов
/ 16 мая 2011

Вы должны включить {% csrf_token %} в шаблон вашей формы между вашими <form> тегами.

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

Если csrf_token не отображается в вашей форме, убедитесь, что вы предоставляетеRequestContext в ответе представления:

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))

Или используйте этот быстрый способ:

from django.views.generic.simple import direct_to_template

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

RequestContext всегда доступен при использовании общих представлений.

2 голосов
/ 10 августа 2011

выше используйте "request.POST", а не "c.POST" в 3-й строке

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

и измените в "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
2 голосов
/ 17 мая 2011

Полагаю, вы пропустили символ '=' в объявлении формы.

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

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

К счастью, это может быть не ошибкой. Так что, если это не решение, попробуйте более простой пример:

# 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="/foo" method = "post">
    {% csrf_token %}
    <input type="text" name="output"></input>
    <input type="submit" value="go"></input>
</form>
<p> Output: {{ output }} </p>
</html>

Надеюсь, это сработает

...