2016-04-21 1 views
0

je besoin d'une forme de courrier électronique et j'essaie ceci:Mise en erreur 403 (CSRF jeton manquant ou incorrect)

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

Mais co nstantly je reçois une erreur 403. J'ai essayé différentes solutions du web, mais rien n'a aidé. Qu'est-ce que je fais mal? Je comprends que quelque chose ne va pas avec csrf dans views.py, mais ne comprends pas où est le problème concrètement.

+0

Votre indentation est incorrecte. Répare le. – 7stud

+0

@ 7stud corrigé, merci –

+0

Avez-vous le middleware CSRF activé 'django.middleware.csrf.CsrfViewMiddleware'? –

Répondre

1

Votre problème est render_to_reponse. Il n'a pas l'instance de contexte, vous pouvez l'ajouter, mais render gère cela pour vous, alors pourquoi ne pas simplement à la place. Vous pouvez également restructurer votre vue pour être un peu plus propre.

Voici un exemple.

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

Ensuite, vous pouvez utiliser {% if messages %} dans votre modèle pour afficher vos messages à l'utilisateur/itérer sur eux et l'affichage.

messages ici est de django.contrib de sorte que vous aurez besoin de faire from django.contrib import messages

+1

Merci, ça marche! Je vais lire à propos de la différence entre render et render_to_response! –

0

Il suffit de modifier votre view.py comme celui-ci

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

Quelle version de django utilisez-vous?

Eh bien, évidemment, vous utilisez render() dans une partie de votre code. Le problème est dans votre code GET - vous utilisez render_to_response():

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

Utilisez plutôt render():

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

Voir la example in the Django docs.

La raison pour laquelle vous devez faire est parce que avec des jetons CSRF vous devez:

  1. Insérez le jeton CSRF dans votre formulaire.

  2. Incluez le jeton csrf en tant que cookie dans les en-têtes de la requête/réponse.

render() # 2 accomplit, mais render_to_response() ne fonctionne pas - à moins que vous dites spécifiquement à, que vous ne l'avez pas. Dans tous les cas, l'état django 1.9 docs:

render_to_response()

Cette fonction a précédé l'introduction de render() et fonctionne de la même sauf qu'il ne fait pas la demande disponible dans la réponse . Il n'est pas recommandé et risque d'être obsolète dans le futur .

+0

Merci, je l'ai eu :) –