2013-02-27 16 views
5


In Django (e in generale), è un cookie anche un'intestazione, proprio come, ad es. User-Agent?
Cioè, questi due metodi sono equivalenti in Django?

Utilizzando set_cookie:
Cookie e intestazioni Django

response.set_cookie('food', 'bread') 
response.set_cookie('drink', 'water') 

Utilizzando impostazione intestazione:

response['Cookie'] = ('food=bread; drink=water') 
# I'm not sure whether 'Cookie' should be capitalized or not 


Inoltre, se siamo in grado di impostare un cookie con il secondo modo, come possiamo comprendere informazioni aggiuntive,
come path, max_age, ecc. Nella stringa? Dobbiamo semplicemente separarli con qualche carattere speciale ?

risposta

3

Sarebbe molto più semplice se si utilizza set_cookie. Ma sì, è possibile impostare il cookie dal impostando l'intestazione della risposta:

response['Set-Cookie'] = ('food=bread; drink=water; Path=/; max_age=10') 

Tuttavia, poiché il ripristino Set-Cookie in response oggetto sarà chiaro il precedente uno, non si può avere più di un Set-Cookie di intestazione in Django. Vediamo perché.

Osservare in response.py, set_cookie method:

class HttpResponseBase: 

    def __init__(self, content_type=None, status=None, mimetype=None): 
     # _headers is a mapping of the lower-case name to the original case of 
     # the header (required for working with legacy systems) and the header 
     # value. Both the name of the header and its value are ASCII strings. 
     self._headers = {} 
     self._charset = settings.DEFAULT_CHARSET 
     self._closable_objects = [] 
     # This parameter is set by the handler. It's necessary to preserve the 
     # historical behavior of request_finished. 
     self._handler_class = None 
     if mimetype: 
      warnings.warn("Using mimetype keyword argument is deprecated, use" 
          " content_type instead", 
          DeprecationWarning, stacklevel=2) 
      content_type = mimetype 
     if not content_type: 
      content_type = "%s; charset=%s" % (settings.DEFAULT_CONTENT_TYPE, 
        self._charset) 
     self.cookies = SimpleCookie() 
     if status: 
      self.status_code = status 

     self['Content-Type'] = content_type 

    ... 

    def set_cookie(self, key, value='', max_age=None, expires=None, path='/', 
        domain=None, secure=False, httponly=False): 
     """ 
     Sets a cookie. 

     ``expires`` can be: 
     - a string in the correct format, 
     - a naive ``datetime.datetime`` object in UTC, 
     - an aware ``datetime.datetime`` object in any time zone. 
     If it is a ``datetime.datetime`` object then ``max_age`` will be calculated. 

     """ 
     self.cookies[key] = value 
     if expires is not None: 
      if isinstance(expires, datetime.datetime): 
       if timezone.is_aware(expires): 
        expires = timezone.make_naive(expires, timezone.utc) 
       delta = expires - expires.utcnow() 
       # Add one second so the date matches exactly (a fraction of 
       # time gets lost between converting to a timedelta and 
       # then the date string). 
       delta = delta + datetime.timedelta(seconds=1) 
       # Just set max_age - the max_age logic will set expires. 
       expires = None 
       max_age = max(0, delta.days * 86400 + delta.seconds) 
      else: 
       self.cookies[key]['expires'] = expires 
     if max_age is not None: 
      self.cookies[key]['max-age'] = max_age 
      # IE requires expires, so set it if hasn't been already. 
      if not expires: 
       self.cookies[key]['expires'] = cookie_date(time.time() + 
                  max_age) 
     if path is not None: 
      self.cookies[key]['path'] = path 
     if domain is not None: 
      self.cookies[key]['domain'] = domain 
     if secure: 
      self.cookies[key]['secure'] = True 
     if httponly: 
      self.cookies[key]['httponly'] = True 

Due cose vale la pena notare qui:

  1. set_cookie metodo si occuperà di gestire datetime in expires per voi, e si dovrà impostare da soli se l'hai impostato tu stesso
  2. self.cookie è un dizionario di dizionari. Quindi ogni key aggiungerà un ["Set-Cookie"] nell'intestazione, come vedrai tra poco.

Scopo cookies all'interno HttpResponse quindi ottenere passato a WSGIHandler, e ottenere aggiunto all'intestazione di risposta:

response_headers = [(str(k), str(v)) for k, v in response.items()] 
for c in response.cookies.values(): 
    response_headers.append((str('Set-Cookie'), str(c.output(header='')))) 

Il codice sopra è anche perché solo set_cookie() consentire più Set-Cookie nell'intestazione di risposta, e che l'impostazione del cookie direttamente sull'oggetto Response restituirà solo uno Set-Cookie.

0

Certo, ma cambiare "Cookie" in "Set-Cookie" e aggiungere "Percorso = /" per renderlo sito largo.

response["Set-Cookie"] = "food=bread; drink=water; Path=/" 

Edit:

Dopo aver provato questo fuori mi sono trovato un cavillo interessante, set_cookie non si raggruppano i cookie simili (stessa strada, scade, dominio, ecc) nella stessa intestazione. Aggiunge semplicemente un altro "Set-Cookie" nella risposta. Comprensibile, poiché il controllo e il disbrigo delle stringhe richiederebbero probabilmente più tempo rispetto all'utilizzo di alcuni byte aggiuntivi nelle intestazioni HTTP (e nel migliore dei casi sarebbe una micro ottimizzazione).

response.set_cookie("food", "kabanosy") 
response.set_cookie("drink", "ardbeg") 
response.set_cookie("state", "awesome") 

# result in these headers 
# Set-Cookie: food=kabonosy; Path=/ 
# Set-Cookie: drink=ardbeg; Path=/ 
# Set-Cookie: state=awesome; Path=/ 

# not this 
# Set-Cookie:food=kabanosy; drink=ardbeg; state=awesome; Path=/ 
+0

Quindi, se devo impostare due cookie diversi, con diversi parametri 'path' e' max_age'; ma usando la sintassi 'response [" Set-Cookie "] = ...'? –

+0

Per essere onesti, è meglio usare 'set_cookie' perché non c'è alcun beneficio reale dall'impostare personalmente le intestazioni. Sarebbe qualcosa di simile però: 'response [" Set-Cookie "] =" food = kabanosy; Max-Age = 86400; Path =/"'. – Matt

+0

So che è fondamentalmente più conveniente usare 'set_cookie', ma mi piacerebbe capire la sua relazione con l'oggetto' HttpResponse' e ​​con le intestazioni. –

1

Un frammento dal codice di HttpResponse classe:

class HttpResponse(object): 

    #... 

    def __init__(self, content='', mimetype=None, status=None, 

     #... 

     self.cookies = SimpleCookie() 

    #... 

    def set_cookie(self, key, value='', max_age=None, expires=None, path='/', 
        domain=None, secure=False, httponly=False): 

     self.cookies[key] = value 

     #... 


Cioè, ogni volta response.set_cookie() si chiama, neanche pone un nuovo cookie
value a response.cookies[key] o cambia l'esistente valore se ce n'è uno in quella chiave.
Spiega perché imposta più intestazioni Set-Cookie.
Mi chiedo come potremmo fare la stessa cosa con response['Set-Cookie'].

Problemi correlati