我在Websilte中使用django创建了一个广告应用,广告模型如下所示
AdModel(models.Model):
starting_date = models.DateField()
expiring_date = models.DateField()
active = models.BooleanField(default=False)
我的目标是使用芹菜创建一个任务来激活(设置ad.active = True)并根据其开始日期和到期日期停用广告,并且由于芹菜节拍是用于周期性的重复任务,它不会解决它。
可能将 starting_date 作为eta传递给这样的任务将是解决方案:
#signals.py
@receiver(post_save, sender=AdModel)
def start_task(sender, instance, created, **kwargs):
if created:
ad_activator_task.apply_async( (instance.id), eta=instance.starting_date)
如果 instance.starting_date 距现在还有3个月了,它将执行吗?我已经读过Celery not usefull for long term future tasks (far future),我有点困惑。
注意:我将Redis用作经纪人
答案 0 :(得分:0)
我强烈建议不将其与计划任务一起实施。最好还是不要使用const express = require('express');
const bodyParser = require('body-parser');
const proxy = require('http-proxy-middleware');
const httpStatus = require('http-status-codes');
const app = express();
app.use(bodyParser.json());
app.use(function (req, res, next) {
console.log("this is where you transform the request");
});
function restreamReq(proxyReq, req, res) {
if (!req.body) {
return;
}
const contentType = req.get('content-type');
if (contentType) {
proxyReq.setHeader('content-type', contentType);
}
const contentLength = req.get('content-length');
if (contentLength) {
const bodyData = JSON.stringify(req.body);
const bufferLength = Buffer.byteLength(bodyData);
if (bufferLength != contentLength) {
console.warn(`buffer length = ${bufferLength}, content length = ${contentLength}`);
proxyReq.setHeader('content-length', bufferLength);
}
proxyReq.write(bodyData);
}
}
function restreamRes(proxyRes, req, res) {
res.status(proxyRes.statusCode);
for (const key of Object.keys(proxyRes.headers)) {
let rawValue = proxyRes.headers[key];
if (!Array.isArray(rawValue)) {
rawValue = [ rawValue ];
}
for (const value of rawValue) {
res.set(key, value);
}
}
console.log("this is where you transform the response");
let body = new Buffer('');
const bodyPromise = new Promise(function(resolve, reject) {
proxyRes.on('data', (data) => body = Buffer.concat([body, data]));
proxyRes.on('end', () => resolve());
proxyRes.on('error', (err) => reject(err));
});
bodyPromise
.then(() => res.end(body))
.catch(err => res.status(httpStatus.INTERNAL_SERVER_ERROR).end());
}
app.use(proxy({
target: 'http://localhost:8080',
changeOrigin: true,
xfwd: false,
preserveHeaderKeyCase: true,
selfHandleResponse: true,
onProxyReq: restreamReq,
onProxyRes: restreamRes,
}));
const server = app.listen(process.env.PORT || 8081);
process.on('SIGINT', function() {
server.close();
process.exit();
});
字段:这里的广告是否有效取决于active
和starting_date
。因此,我们可以将其建模为:
expiring_date
我们可以使用注释来确定class AdModel(models.Model):
starting_date = models.DateField()
expiring_date = models.DateField()
是否在以下情况下处于活动状态:
AdModel
如果您经常需要这样做,可以制作一个from django.db.models import BooleanField, ExpressionWrapper, Q
from django.db.models.functions import Now
AdModel.objects.annotate(
active=ExpressionWrapper(
Q(starting_date__lte=Now(), expring_date__gte=Now()),
output_field=BooleanField()
)
)
来自动注释Manager
:
AdModel.objects
如果您想要额外的控制,则可以添加一个默认为NULL的额外可空布尔字段class AdModelManager(models.Manager):
def get_queryset(self):
return super().get_queryset().annotate(
active=ExpressionWrapper(
Q(starting_date__lte=Now(), expring_date__gte=Now()),
output_field=BooleanField()
)
)
class AdModel(models.Model):
starting_date = models.DateField()
expiring_date = models.DateField()
objects = AdModelManager()
,但可以将其设置为force_active
/ True
来覆盖到期机制:
False
答案 1 :(得分:0)
我想出了一个不错的解决方法,希望创建一个定期执行的任务,该任务每天在午夜运行,以检查广告是否已激活/停用,该任务是这样的:
#tasks.py
@shared_task
def activate_deactivate_ads():
to_activate = AdModel.objects.filter(date_started=timezone.now().date())
if to_activate.exists():
to_activate.update(active=True)
to_deactivate = AdModel.objects.filter(date_expires=timezone.now().date(), active=True)
if to_deactivate.exists():
to_deactivate.update(active=False)
和节拍配置:
#settings.py
CELERY_BEAT_SCHEDULE = {
'activate-deactivate-ads': {
'task': 'tasks.activate_deactivate_ads',
# Excecute everyday at midnight
'schedule': crontab(minute=0, hour=0),
}
}
欢迎其他任何方法