2016-04-21 10 views
0

ich einige E-Mail-Formular benötigen, und ich versuche dies:Erste Fehler 403 (CSRF-Token fehlenden oder falschen)

views.py

def send_email(request): 
    if request.method != 'POST': 
     form = EmailForm() 
     return render_to_response('mail_form.html', {'email_form': form}) 

    form = EmailForm(request.POST, request.FILES) 
    if form.is_valid(): 
     subject = form.cleaned_data['subject'] 
     message = form.cleaned_data['message'] 
     email = form.cleaned_data['email'] 
     attach = request.FILES['attach'] 
     try: 
      mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email]) 
      mail.attach(attach.name, attach.read(), attach.content_type) 
      mail.send() 
      return render(request, 'mail_form.html', {'message': 'Sent email to %s'%email}) 
     except: 
      return render(request, 'mail_form.html', {'message': 'Either the attachment is too big or corrupt'}) 
     return render(request, 'mail_form.html', {'message': 'Unable to send email. Please try again later'}) 

forms.py

class EmailForm(forms.Form): 
    email = forms.EmailField() 
    subject = forms.CharField(max_length=100) 
    attach = forms.Field(widget=forms.FileInput) 
    message = forms.CharField(widget = forms.Textarea) 

mail_form.html

... 
{{message}} 
<form method="post" action=""> 
    {% csrf_token %} 
    {{ email_form.as_p }} 
    <input type ="submit" name = "send" value = "Send"/> 
</form> 
... 

Aber co Fast immer bekomme ich einen Fehler 403. Ich habe versucht verschiedene Lösungen aus dem Internet, aber nichts half. Was mache ich falsch? Ich verstehe, dass etwas mit csrf in views.py nicht stimmt, aber verstehe nicht, wo das Problem konkret ist.

+0

Ihre Einrückung ist nicht korrekt. Repariere es. – 7stud

+0

@ 7stud behoben, danke –

+0

Haben Sie die CSRF-Middleware aktiviert 'django.middleware.csrf.CsrfViewMiddleware'? –

Antwort

1

Ihr Problem ist render_to_reponse. Es hat nicht die Kontextinstanz, die Sie hinzufügen können, aber render behandelt dies für Sie, also warum nicht nur es stattdessen. Außerdem können Sie Ihre Ansicht neu strukturieren, um ein wenig sauberer zu sein.

Hier ist ein Beispiel.

def send_email(request): 

    if request.method == 'POST': 
     form = EmailForm(request.POST, request.FILES) 
     if form.is_valid(): 
      subject = form.cleaned_data['subject'] 
      message = form.cleaned_data['message'] 
      email = form.cleaned_data['email'] 
      attach = request.FILES['attach'] 
      try: 
       mail = EmailMessage(subject, message, settings.EMAIL_HOST_USER, [email]) 
       mail.attach(attach.name, attach.read(), attach.content_type) 
       mail.send() 
       messages.succes(request, 'Sent an email to %s' % email) 
      except: 
       messages.error(request, 'Either the attachment is too big or corrupt') 
    else: 
     form = EmailForm() 
     messages.info(request, "Send an email!") 
    return render(request, 'mail_form.html', {'email_form': form}) 

Dann können Sie {% if messages %} in Ihrer Vorlage verwenden, um Ihre Nachrichten an den Benutzer anzuzeigen/iterieren sie und Anzeige.

messages hier ist von django.contrib so würden Sie from django.contrib import messages

+1

Danke, es funktioniert! Ich lese über den Unterschied zwischen render und render_to_response! –

0

ändern Sie Ihre view.py wie diese

from django.shortcuts import render 
from django.template import RequestContext 
def send_email(request): 
if request.method != 'POST': 
    form = forms.EmailForm() 
    return render_to_response('mail_form.html', {'email_form': form}, context_instance=RequestContext(request)) 

...... 
...... 
0

Welche Version von django verwenden Sie?

Nun, offensichtlich verwenden Sie render() in einem Teil Ihres Codes. Das Problem ist in Ihrem GET-Code - Sie render_to_response() verwenden:

if request.method != 'POST': 
    form = EmailForm() 
    return render_to_response('mail_form.html', {'email_form': form}) 

Stattdessen machen() verwenden:

return render(request, 'mail_form.html', {'email_form': form}) 

die example in the Django docs See.

Der Grund, warum Sie brauchen, das zu tun ist, weil mit csrf Tokens Sie müssen:

  1. die csrf Token in Ihrem Formular ein.

  2. Fügen Sie das csrf-Token als Cookie in die Header der Anfrage/Antwort ein.

render() erreicht # 2, aber render_to_response() nicht - es sei denn, Sie es ausdrücklich sagen, was Sie nicht. In jedem Fall ist der django 1.9 docs Zustand:

render_to_response()

Diese Funktion voran die Einführung von render() und arbeitet außer in ähnlicher Weise, dass es nicht macht nicht verfügbar die Anforderung in der Antwort . Es wird nicht empfohlen und wird voraussichtlich in der Zukunft veraltet sein.

+0

Danke, ich habe es :) –