我想创建一个带有工人的应用程序,该应用程序在后台更改模拟模型的值。首先,用户点击开始模拟,等待一段时间,点击结束模拟,然后在页面上显示由后台工作人员更改的值差(从模拟开始到结束(。主要问题是我无法完成工人的任务。我可以在模拟模型保存后联系@receiver,并正确检查模型的值,但我不能由工人更改数据库中的模型值。
该项目名为app,application-myapp。
app/myapp/models.py
from django.db import models
class Simulation(models.Model):
# changed every simul day
created_date = models.DateField(auto_now_add=True)
today = models.DateField(auto_now=False, auto_now_add=False)
status = models.BooleanField(default=False)
daemon_active = models.BooleanField(default=False)
info = models.TextField()
def get_simulation_day(self):
"""days passed after simulation firstly start"""
# sim = Simulation.objects.all().last()
return (self.today - self.created_date).days
app/myapp/views.py
def simulate(request, action):
sim = get_simulation()
if action == "disable" and sim.status == True:
sim.status = False
sim.save()
elif action == "enable" and sim.status == False:
print('view simulate ok')
sim.status = True
sim.save()
print('view simulate ok after save')
context = {
"simulations_exists": True,
"days_passed": sim.get_simulation_day(),
"simulation_today_str": (sim.today).strftime("%d %B, %Y"),
"simulation_status": sim.status
}
return render(request, "simulation_page.html", context=context)
app/myapp/tasks.py
import logging
from django.urls import reverse
from django.core.mail import send_mail
from django.contrib.auth import get_user_model
from app.celery import app
from django.db.models.signals import post_save, pre_save
from django.dispatch import receiver
from .models import Simulation
# import myapp.models
@app.task
def simulate_days(sim_id):
sim = Simulation.objects.get(id=sim_id)
print('nnstart in simulate_daysnn')
it = 0
while sim.status == True:
it += 1
print(f'nn {it} iter in simulate_daysnn')
sim.daemon_active = True
sim.today = sim.today + timedelta(1)
time.sleep(5)
sim.refresh_from_db()
sim.save()
sim.refresh_from_db()
print('nnend in simulate_daysnn')
sim.daemon_active = False
sim.save()
@receiver(post_save, sender=Simulation)
def simulation_daemon(sender, instance, created, **kwargs):
if instance.status == True and instance.daemon_active == False:
print('start simulation_daemon')
simulate_days.delay(instance.id)
print('end simulation_daemon')
在app/settings.py我使用postgres并添加redis设置
# REDIS related settings
REDIS_HOST = 'localhost'
REDIS_PORT = '6379'
BROKER_URL = 'redis://' + REDIS_HOST + ':' + REDIS_PORT + '/0'
BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 3600}
CELERY_RESULT_BACKEND = 'redis://' + REDIS_HOST + ':' + REDIS_PORT + '/0'
app/celery.py
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
app = Celery('app')
app.config_from_object('django.conf:settings')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
在启动服务器之前,我首先设置了redis,然后设置了芹菜,它按预期工作。对于redi,我在控制台中键入:
redis-server
我得到:
[14604] 20 Nov 23:12:55 - DB 0: 4 keys (1 volatile) in 8 slots HT.
[14604] 20 Nov 23:12:55 - 11 clients connected (0 slaves), 1280840 bytes in use
芹菜:
celery worker -A app --loglevel=debug --concurrency=4
在输出中,我得到
[2019-11-20 23:12:03,182: DEBUG/MainProcess] Timer wake-up! Next ETA 1.0 secs.
[2019-11-20 23:12:04,184: DEBUG/MainProcess] Timer wake-up! Next ETA 1.0 secs
我认为您的问题是在您的任务中更改为today
的值之后立即使用refresh_from_db
引起的。这将导致任何更改的值都被数据库中保存的内容覆盖。在这种情况下,它永远不会允许更改today
值。
sim.today = sim.today + timedelta(1)
time.sleep(5)
sim.refresh_from_db() # This will overwrite the `today` value you set in the line above
sim.save() # This will just save the old value that was already in the DB