2011-02-27 24 views
17

Quiero guardar algunas cosas en una base de datos, y estoy usando la sesión actual como una clave externa: de models.pyDjango: el establecimiento de una sesión y obtener la clave de sesión en el mismo punto de vista

class Visited(models.Model): 
    session = models.ForeignKey(Session) 
    page = models.ForeignKey(Page) 
    times_visited = models.PositiveIntegerField() 
    ip_address = models.IPAddressField() 
    date_last_visited = models.DateTimeField() 
    def __unicode__(self): 
     return u'(%s, %s)' % (str(self.session.session_key), str(self.page.name)) 

Para hacer una nueva entrada para este modelo estoy usando el siguiente para obtener la sesión actual (en views.py):

Session.objects.get(session_key=request.session.session_key) 

sin embargo, si es la primera vez que un usuario ha visitado el sitio, y por lo tanto no tienen un conjunto de cookies, el código anterior generará un error DoesNotExist.


sé que incluso si no es ahora cookie establecida todavía se puede configurar objetos de sesión. Así que puedo pensar en algunos hacks para hacer este trabajo, tales como:

  • Establecer identificador único como un objeto de sesión (además de la clave de sesión)
  • almacenar temporalmente los datos que desea añadir a la base de datos de un objeto de sesión, y use una función de decorador para verificar si existe antes de usar una sesión.
  • Simplemente use los objetos de sesión y no almacene nada en la base de datos (esto sería técnicamente posible, pero para mi implementación dependería de los diccionarios de Python, con unos cientos de entradas, al menos tan eficiente como una base de datos para cosas como de clasificación.)


Pero me gustaría una solución mejor que puedo vivir con. ¿Hay soluciones generalmente usadas o buenas para este problema? ¿O incluso estoy haciendo referencia a las sesiones correctamente en mi modelo?

Gracias por su ayuda.

Respuesta

39

request.session es un SessionStore object con un session_key único.

La session_key se crea tan pronto como se accede al atributo. Pero el objeto de sesión en sí mismo solo se guarda en la base de datos después de que la vista ha sido procesada (en el método process_response del middleware de sesión) llamando al método save del objeto SessionStore.

Realmente no está documentado, pero mirando el código fuente supongo que suponen para crear un nuevo objeto de sesión como esto:

if not request.session.exists(request.session.session_key): 
    request.session.create() 

También puede crear la sesión de middleware personalizada, que asegura que su nueva sesión objeto está siempre disponible antes que cualquiera de sus puntos de vista trata de acceder a ella:

from django.conf import settings 
from django.contrib.sessions.middleware import SessionMiddleware 

class CustomSessionMiddleware(SessionMiddleware): 
    def process_request(self, request): 
     engine = import_module(settings.SESSION_ENGINE) 
     session_key = request.COOKIES.get(settings.SESSION_COOKIE_NAME, None) 
     request.session = engine.SessionStore(session_key) 
     if not request.session.exists(request.session.session_key): 
      request.session.create() 

(Por supuesto debe hacer referencia a su nuevo middleware sesión a través de SESSION_ENIGNE dentro de su settings.py)

Pero tenga en cuenta que este enfoque generará un nuevo objeto de sesión para cada solicitud si el navegador del usuario no admite cookies ...

+0

Gracias por su excelente explicación de cómo funciona todo (o más bien por qué no funciona) t trabajo). Fui con una variación del segundo "truco" que mencioné, en aras de la simplicidad, si no de la elegancia. –

+0

No estoy muy familiarizado con Django o Python, pero estoy bastante seguro de que esta respuesta es exactamente lo que necesito. Necesito cambiar la sesión si se pasa una identificación de sesión del cliente (no pregunte). Aunque estoy un poco confundido, ¿hago referencia a esta clase en 'MIDDLEWARE_CLASSES' además de 'django.contrib.sessions.middleware.SessionMiddleware' y también' SESSION_ENGINE'? Seguramente al hacer referencia en 'SESSION_ENGINE' hace que esta línea se repita? 'engine = import_module (settings.SESSION_ENGINE)'. ¿Me estoy perdiendo el punto? – Steve

+0

No creo que 'request.session.create()' establezca el encabezado 'Set-Cookie'. – Flimm

Cuestiones relacionadas