2013-11-21 3 views
6

Sono nuovo di Python. Anche nuovo per Django. Sto cercando di fare una richiesta AJAX e ho seguito le istruzioni here. all'inizio, il risultato del recupero del cookie csrf era sempre nullo, quindi ho trovato un metodo decorator chiamato ensure_csrf_cookie. Il problema è che richiede una vista, e non ho idea di quale vista passare e dove posso ottenere un riferimento ad essa. Il codice è abbastanza semplice:come si usa ensure_csrf_cookie?

from django.shortcuts import render_to_response 
from django.core.context_processors import csrf 
from django.views.decorators.csrf import ensure_csrf_cookie 

def csv_to_xform(csv, template): 
    return render_to_response(template, { "data": "it works!" }) 

Devo utilizzare una vista basata sulla classe? se è così, c'è un modo migliore per impostare il cookie? Mi piacerebbe non usare il metodo descritto here, perché non voglio dover gestire manualmente il valore.

Il resto del codice è il seguente:

sandbox.html:

<!doctype html> 

<html> 
    <head> 
     <title>Sandbox</title> 

     <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script> 
     <script src="/static/js/csrf.js"></script> 

     <script type="text/javascript"> 
      $(function() { 
       $('#send-csv-btn').click(function() { 
        $.post('/csv', { 
         data: '1, 2, 3', 
         success: function (response) { 
          console.debug(response); 
         }, 
         error: function (response) { 
          console.debug(response); 
         } 
        }); 
       }); 
      }); 
     </script> 
    </head> 

    <body> 
     <form> 
      {% csrf_token %} 
      <input type="button" id="send-csv-btn" /> 
     </form> 
    </body> 
</html> 

urls.py:

urlpatterns = patterns('', 
    url(r'^$', 'dkobo.formbuilder.views.main', name='fb'), 
    url(r'^admin/', include(admin.site.urls)), 
    url(r'^csv$', 'dkobo.formbuilder.views.csv_to_xform', { "template": "sandbox-stub.html" }), 
    url(r'^sandbox$', 'dkobo.formbuilder.views.sandbox') 
) 

settings.py:

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware', 
    'django.middleware.common.CommonMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
    'django.contrib.auth.middleware.AuthenticationMiddleware', 
    'django.contrib.messages.middleware.MessageMiddleware', 
    'django.middleware.clickjacking.XFrameOptionsMiddleware', 
) 

risposta

11

I cookie impostati sulla risposta del server, quindi è necessario impostare @ensure_csrf_cookie decorator per la visualizzazione, che esegue il rendering della pagina, da cui l'utente effettuerà una richiesta di jax.

Ad esempio, se il browser degli utenti effettua una richiesta di jax sulla pagina principale dei siti, impostare questo decoratore per la visualizzazione, responsabile della pagina principale.

UPDATE: ajax richiede chiamate dalla pagina sandbox? poi tenta di impostare ensure_csrf_cookie per la vista sandbox, in questo modo:

@ensure_csrf_cookie 
def sandbox(request): 
... 
+0

Ho caricato il resto del codice ... potresti fare un esempio? –

+0

ho aggiornato la risposta – Nikita

+0

ottima, ha funzionato! Grazie. –

3

I token CSRF vengono automaticamente convalidati n avete:

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

nel file di progetto settings.py.

Quando si dispone di tale middleware, è necessario solo per mettere variabile crsf_token a tutti i moduli (nei modelli), ed è convalidato automaticamente, ad esempio:

<form> 
{% csrf_token %} 
... 

Non so se ho capito la tua problema)

+0

secondo quello che ho capito, il {% csrf_token%} '' elemento deve essere all'interno di un modulo. Potrei non avere un modulo sul mio modello (in questo caso lo faccio, ma è la sandbox). Fondamentalmente voglio essere in grado di impostare il cookie senza un elemento del modulo –

+0

Ho provato quello che dici, e non ha funzionato. '{% csrf_token%}' non restituisce nulla. Sto aggiornando il post per includere il resto del codice pertinente. –

3

Anche se hai trovato quello che cercavi per questi concetti vi aiuterà.

Le viste sono funzioni che vengono richiamate quando viene richiesto un URL. E ci sono due tipi di visualizzazioni: viste basate

  1. funzione Visto basate
  2. Class.

Il funzionamento di base della vista è elaborare una richiesta Http e inviare una risposta Http. E ogni vista che restituisce HttpResponse deve avere un parametro di richiesta.

Ex di una vista basata funzione:

def myView(request): 
    ... 
    # process the request here 
    return HttpResponse() # or render_to_response depending upon what you want. 

non vedo un parametro request nella vista.

Ora un decoratore è qualcosa che mette determinate condizioni in una vista.

Ad esempio: Se si dispone della funzione di visualizzazione per i commenti e si desidera che l'utente effettui il login per commentare, è possibile utilizzare un decoratore login_required nella vista.

Ciò garantirà che chiunque desideri commentare dovrà prima effettuare il login. La sintassi di base è:

@login_required # this is the decorator 
def comment(request): # this is the view on which the decorator is acting upon 
... 
... 
return HttpResponse() 

Simile al @login_required, @ensure_csrf_cookie è un decoratore.

+0

aahhh ora ho capito! Conoscevo la parte sulle viste e ho appena scoperto che il primo argomento passato è l'oggetto della richiesta. Non sapevo che i decoratori erano diversi dalle normali funzioni. Grazie per averlo chiarito! –

+0

il mio piacere .... –

+0

dove lo metto in una visualizzazione basata su classi? per esempio. 'HyperLinkedModelViewSet' di DRF? – Jayen

9

Per chi cerca un modo per fare questo con vista basata classe:

from django.utils.decorators import method_decorator 
from django.views.decorators.csrf import ensure_csrf_cookie 

class MyView(View): 

    @method_decorator(ensure_csrf_cookie) 
    def get(self, request, *args, **kwargs): 
     ...