我正通过主管在我的远程Ubuntu服务器上运行Celery / Django。我的系统可以从我的City
成功接收并执行我的2个任务。
tasks.py
然而,当我使用:
@periodic_task(run_every=timedelta(minutes=1))
def test_job():
from polls.models import Question
from post.models import Post #when I add this line, it fires the error
for i in Question.objects.all():
if i.question_text == "test":
i.question_text = "not_test"
i.save()
return HttpResponseRedirect('/')
@periodic_task(name='run_scheduled_jobs', run_every=timedelta(seconds=30))
def run_scheduled_jobs():
return True
在我的任务中,任务失败:
我尝试从我所有其他模块中导入模型,它工作正常;例如from post.models import Post
和from Comment.models import Comment
工作正常。由于某种原因,它不允许我导入from poll.models import Question
。
以下是from post.models import Post
文件:
post.models
知道为什么它不允许我导入from django.db import models
from django.contrib.auth.models import AbstractUser, User
from django.conf import settings
#from django.contrib.humanize import naturaltime
from django.apps import apps
from draft1.choices import CATEGORY_CHOICES
from django.utils import timezone
import requests
import tempfile
from django.core import files
from django.core.files import File as FileWrapper
from datetime import datetime, timedelta
from math import log10
from urllib import parse
from urllib.parse import urlparse
import boto3
# import uuid
from functions.helper_functions import random_string
from math import log, exp
from draft1.choices import DURATION_CHOICES
class Post(models.Model):
hash = models.CharField(max_length=18, default=random_string, null=True, blank=True)
user = models.ForeignKey(User, blank=True, null=True)
has_upvoted = models.ManyToManyField(User, related_name="has_upvoted", blank=True)
has_downvoted = models.ManyToManyField(User, related_name="has_downvoted", blank=True)
title = models.TextField(max_length=95)
second_title = models.TextField(max_length=95, blank=True, null=True)
dots1 = models.CharField(max_length=90, blank=True)
dots2 = models.CharField(max_length=90, blank=True)
dots3 = models.CharField(max_length=90, blank=True)
last_modified = models.DateTimeField(auto_now=True)
date = models.DateTimeField(auto_now_add=True)
content = models.TextField(null=True, blank=True)
image = models.FileField(null=True, blank=True)
imageURL = models.URLField(null=True, blank=True)
video = models.BooleanField(default=False)
thumbnail = models.ImageField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
entered_category = models.CharField(max_length=80, default='news')
ad = models.BooleanField(default=False)
total_comments = models.IntegerField(default=0)
post_score = models.ForeignKey('post.PostScore', related_name='post_score', blank=True, null=True)
hot = models.IntegerField(default=0)
def handle_uploaded_file(f, filename):
with open('/tmp/%s' % filename, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
@property
def video_source(self):
if self.imageURL:
t = urlparse(self.imageURL).netloc
domain = '.'.join(t.split('.')[1:])
if domain == "youtube.com":
return "youtube"
else:
return "standard"
def __str__(self):
return self.title
class AdvertisePost(Post):
url = models.CharField(max_length=200, blank=True, null=True)
position = models.IntegerField(default=DURATION_CHOICES[2][0], choices=DURATION_CHOICES)
duration = models.IntegerField(default=48)
total_price = models.IntegerField(default=20)
activated = models.BooleanField(default=False)
counter = models.IntegerField(default=0, null=True, blank=True)
def __str__(self):
return self.title
class PostScore(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
post = models.ForeignKey(Post, related_name='score')
upvotes = models.IntegerField(default=0)
downvotes = models.IntegerField(default=0)
def hot(self):
s = self.upvotes
baseScore = log(max(s, 1))
now = datetime.now()
timeDiff = (now - self.post.date).days
if (timeDiff > 1):
x = timeDiff - 1
baseScore = baseScore * exp(-8 * x * x)
return baseScore
class Room(models.Model):
name = models.CharField(max_length=68)
frequency = models.IntegerField(default=1)
comments = models.IntegerField(default=0)
created = models.DateTimeField(auto_now_add=True)
?
PS:模块post.models
肯定存在,当我从其他文件(例如post.models
等)导入它时,它可以正常工作。
settings.py
views.py
编辑:
我已将CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers.DatabaseScheduler"
CELERYBEAT_SCHEDULE = {
'run_scheduled_jobs': {
'task': 'run_scheduled_jobs',
'schedule': timedelta(seconds=45),
},
'test_job': {
'task': 'tasks.test_job',
'schedule': timedelta(seconds=45),
},
'post_jobs': {
'task': 'post.tasks.post_jobs',
'schedule': timedelta(minutes=1),
},
'test_post': {
'task': 'post.tasks.test_post',
'schedule': timedelta(seconds=45),
}
}
INSTALLED_APPS = [
...
'post',
...
]
添加到我的tasks.py
模块,并相应更改了我的post
:
发表/ tasks.py
settings.py
答案 0 :(得分:0)
您的tasks.py文件可能不在django管理的文件夹下。当我从django项目外部使用依赖于django的模块(作为模型)时,我遇到了这类问题。
您有很多选择:
在任何django模块(apps)中实现tasks.py,即:
├─┬ post
│ ├── __init__.py
│ ├── tasks.py
│ ├── views.py
│ └── urls.py
└── otherapp
在django项目中为芹菜相关逻辑创建一个模块子文件夹:
├─┬ celery
│ ├── __init__.py
│ └── tasks.py
└── post
您还可以将django模型导入仍在django项目外部的tasks.py
。看看this问题。
记住python所需的__init__.py
文件,将文件夹内容作为模块加载。
我希望它有所帮助!
<强>更新强>
我明白了。
在文件开头设置导入是最好的方法。您正在将Post
加载到在芹菜工作者的共享内存中执行的代码中。这与django应用程序管理的内存不同。
尝试在文件的最开始处进行导入:
from polls.models import Question
from post.models import Post # added post here
@periodic_task(run_every=timedelta(minutes=1))
def test_post():
for i in Post.objects.all():
if i.entered_category == "test":
i.entered_category = "not_test"
i.save()
return HttpResponseRedirect('/')
@periodic_task(name='post_jobs', run_every=timedelta(seconds=30)) # task name found! celery will do its job
def post_jobs():
# do whatever stuff you do
return True
如果是这样的话就行了。