Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create object on startup and share across requests

I would like to use my Django application as a relay for a session-based online service and share this session among all users. For this, I've configured a python-requests Session object.

I would like to initialise this Session when Django starts up and keep it alive forever. My idea is to have all requests to my Django application share the session object by allowing the view for the particular request access the session object.

In Flask setting this up (for experimental purposes) is fairly easy:

from flask import Flask, render_template, request, session
from requests import Session
app = Flask(__name__)

session = Session()
session.post()        # Setup Session by logging in

@app.route("/")
def use_session():
    reply = session.get()   # Get resource from web service
    return jsonify(reply)

Here session would be created when starting and can be accessed by use_session().

I struggle to set up the same in Django though. Where would be the preferred place to create the session?

like image 505
nehalem Avatar asked Jan 28 '26 07:01

nehalem


1 Answers

The equivalent of your Flask code in Django would be to put the same logic in a views.py file:

# yourapp/views.py
from django.http import HttpResponse
from requests import Session

session = Session()
session.post('https://httpbin.org/post')  # Setup Session by logging in


def use_session(request):
    reply = session.get('https://example.com')  # Get resource from web service
    return HttpResponse(reply.content, status=reply.status_code)

# yourproject/urls.py
from django.urls import path
from yourapp.views import use_session


urlpatterns = [
    path('', use_session)
]

The object will get created as you start the server.

One problem with this approach is that in a real-world deployment you normally run multiple copies of your app (doesn't matter if it's Flask or Django or any other framework) to avoid thread blocking, utilize multiple CPU cores on the same server or have multiple servers, each copy will end up with its own session, which might work fine, but might be problematic.

In a situation like this, you can share a Python object1 across multiple processes by serializing it using the pickle module and storing the byte data in a database. A good place for the data would be something like Redis or Memcached but Django's ORM can be used as well:

# yourapp/models.py
from django.db import models


class Session(models.Model):
    pickled = models.BinaryField()

# yourapp/views.py
import pickle

from django.http import HttpResponse
from requests import Session

from . import models


def use_session(request):
    # Load the pickled session from the database
    session_db_obj = models.Session.objects.first()

    if session_db_obj:
        # Un-pickle the session
        session = pickle.loads(session_db_obj.pickled)
    else:
        # Create a new session
        session = Session()
        session.post('https://httpbin.org/post')  # Setup Session by logging in

        # Create the database object, pickle the session and save it
        session_db_obj = models.Session()
        session_db_obj.pickled = pickle.dumps(session)
        session_db_obj.save()

    reply = session.get('https://example.com')  # Get resource from web service
    return HttpResponse(reply.content, status=reply.status_code)

1: Not any object can be pickled and unpickled reliably, be careful!

like image 102
Igonato Avatar answered Jan 29 '26 19:01

Igonato