类似于那种定时抢购的逻辑。
时间没到之前是个介绍页面,时间到了之后进入真正的 view 处理函数。
触发条件不一定是时间,也可能是后台控制的。就是要做到程序不重启,同一 url 对应的 view 变了。
我是这样做的,加了个全局变量,然后在 url 对应个 view 函数里做判断,后台改变这个全局变量,执行不同的 view 函数。
IS_RELEASE 是全局变量,entrance 函数是入口函数,release 函数是改变入口的视图函数。
IS_RELEASE = False
def entrance(request):
global IS_RELEASE
if IS_RELEASE:
return index2022(request)
else:
return index2(request)
@login_required
def release(request):
global IS_RELEASE
if IS_RELEASE:
IS_RELEASE = False
else:
IS_RELEASE = True
return redirect("/conf/")
这个方法在本地调试没问题,但是上到服务器后,出现执行 release 函数后 IS_RELEASE 没按预期改变,或者有秒级的延迟,我猜是不是有 cdn 的影响,但是这个都应该是动态页面,每个请求都要回服务器处理的。
1
676529483 2022-08-29 16:22:18 +08:00
你服务器肯定不是 runserver 启动的吧?走 gunicorn 、uwsgi 等等,都是多进程的,全局变量只是进程唯一的,可以改成从一个地方去拿,比如 redis 、mysql
|
4
elboble OP [uwsgi]
chdir = /home/xxxx/project/xxxx module = xxxx.wsgi home = /home/xxxx/venv/venv3.9 master = true processes = 2 socket = 0.0.0.0:8909 vacuum = true |
5
zxzflower 2022-08-29 16:53:46 +08:00
用 redis 或者数据库 做个访问开关,你只要有多个 worker ,你的方法就会混乱的,甚至 worker 还会 restart
|
6
bulay 2022-08-29 16:57:37 +08:00
如果是单台服务器直接用 django.core.cache,本地缓存.
|
7
AndyVTEX 2022-08-29 17:45:35 +08:00
是啊,肯定是 redis 或者数据库开关呀,环境变量是什么骚操作
|
8
lanlanye 2022-08-29 20:04:43 +08:00 via iPhone
建议你把要渲染的模板做成 Model ,需要时直接去 DjangoAdmin 里改……
|
9
elboble OP 感谢各位大佬,用 redis 存了状态,基本实现了功能,上服务器也没问题了。
还有几点请教: 1 ,用 uwsgi 起多个 worker ,实际上是多个 django 的实例在跑,这样如果用 uwsgi 来启动 django ,djaongo 中是不存在只运行一次的代码。 我这个问题中,即使用 redis 也有个初始值的坑。最简单的是在程序之外,程序启动之前,用 redis-cli 手动设定初始值。如果不用这个方法,就想是不是能在 django 初始化的地方,运行一次 redis set 初始值。通过上面的分析,django 用 uwsgi 启动是不存在这样只执行一次的代码,至少每个 worker 启动 django 所有的代码都要跑一遍,有几个 worker 就要跑几遍。 后来我想通过 redis 直接 get 键取值,但是 redis 的 get 不像 json 的 get 读取空时能返回一个默认值,这个真没想到,自己简单包装了一个能返回默认值的,来代替原始的 conn.get()。这样就不需要预先设置 redis 了。 conn = redis.Redis(connection_pool=POOL) IS_RELEASED_KEY = 'xxxx_is_released' def rget(key): ret = conn.get(key) if ret == None: return '0' else: return ret 2 ,取得 redis 的 conn 是在 view.py 中,但是不在任何一个 view 函数中,这个代码是不是每个 worker 只执行一次,有几个 woker 就有几个不同的 conn ,还是每次请求都会建新的 conn ? |
10
zmaplex 2022-08-31 16:45:15 +08:00 via Android
一个小功能还是不要上 redis 了吧,在 django 中类似全局变量效果,请直接用 django 内置的
cache 。 |
12
gaogang 2022-09-05 18:01:59 +08:00
|
13
programMrxu 2023-11-01 17:20:21 +08:00
为什么这里的值不会改变呢?我在本地跑了两个线程,去修改一个全局变量,他的值是会发生变化的。
|
14
elboble OP @programMrxu 我理解是 uwsgi 接受每个请求,是单独开个 django 进程,所以即使全局变量也不能共享,“全局”仅在 django 进程内。所以用系统级的 redis ,杀鸡用牛刀了。
|