在启动时创建对象并跨请求共享



我想使用我的Django应用程序作为基于会话的在线服务的中继,并在所有用户之间共享此会话。为此,我配置了一个python-requests Session对象。

我想在Django启动时初始化这个会话,并使它永远活跃。我的想法是,通过允许特定请求的视图访问会话对象,让所有对Django应用程序的请求共享会话对象。

在<<p> strong>瓶设置(用于实验目的)相当容易:
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)

这里session将在启动时创建,并且可以被use_session()访问。

我努力在Django中设置相同的。创建会话的首选位置是哪里?

在Django中,你的Flask代码相当于将相同的逻辑放在views.py文件中:

# 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)
]

该对象将在您启动服务器时创建。

这种方法的一个问题是,在现实世界的部署中,为了避免线程阻塞,你通常会运行多个应用程序副本(不管它是Flask还是Django或任何其他框架),在同一服务器上使用多个CPU内核或有多个服务器,每个副本最终都会有自己的会话,这可能工作得很好,但可能会有问题。

在这种情况下,您可以通过使用pickle模块序列化Python对象1并将字节数据存储在数据库中来跨多个进程共享该对象。一个存放数据的好地方是Redis或Memcached,但Django的ORM也可以使用:

# 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:不是任何对象都可以可靠地pickle和unpickle,要小心!

设置它的最佳位置可能是在settings.py中,因为它在应用程序初始化之前被调用,您可以轻松地从那里导入代码。

也就是说,您可能想要查看连接池或在会话顶部有一个包装器,以便在失败时重新创建它。网络并不像看起来那么可靠,如果你计划让会话长时间运行,它会增加会话在某个时刻被停止的机会。

最新更新