无法在我的芹菜任务中导入模型

时间:2018-04-28 05:42:15

标签: python django celery supervisord

我正通过主管在我的远程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

在我的任务中,任务失败:

enter image description here

我尝试从我所有其他模块中导入模型,它工作正常;例如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

1 个答案:

答案 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

如果是这样的话就行了。